Fix some -TFTE issues with xonotic.
Implement OP_STOREF_F, but don't generate it just yet (waiting for next 'stable' build). Just disable fteqcc.log by default. If this affects adversely you then you should probably just be using fteqccgui instead. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5698 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
df5b4e4e48
commit
62a4572f23
8 changed files with 263 additions and 83 deletions
|
@ -422,6 +422,102 @@ reeval:
|
|||
*(unsigned char *)ptr = (char)OPA->_float;
|
||||
break;
|
||||
|
||||
case OP_STOREF_F:
|
||||
case OP_STOREF_I:
|
||||
case OP_STOREF_S:
|
||||
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid entity in %s\n", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
|
||||
#ifdef PARANOID
|
||||
NUM_FOR_EDICT(ed); // make sure it's in range
|
||||
#endif
|
||||
errorif (!ed || ed->readonly)
|
||||
{ //boot it over to the debugger
|
||||
#if INTSIZE == 16
|
||||
ddef16_t *d = ED_GlobalAtOfs16(progfuncs, st->a);
|
||||
#else
|
||||
ddef32_t *d = ED_GlobalAtOfs32(progfuncs, st->a);
|
||||
#endif
|
||||
fdef_t *f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
|
||||
if (PR_ExecRunWarning(&progfuncs->funcs, st-pr_statements, "assignment to read-only entity %i in %s (%s.%s)\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), d?PR_StringToNative(&progfuncs->funcs, d->s_name):"??", f?f->name:"??"))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
|
||||
//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
|
||||
#ifdef NOLEGACY
|
||||
errorif (ed->ereftype == ER_FREE)
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "assignment to free entity in %s", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = OPB->_int + progfuncs->funcs.fieldadjust;
|
||||
errorif ((unsigned int)i*4 >= ed->fieldsize) //FIXME:lazy size check
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = (eval_t *)(((int *)edvars(ed)) + i);
|
||||
ptr->_int = OPC->_int;
|
||||
break;
|
||||
case OP_STOREF_V:
|
||||
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid entity in %s\n", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
|
||||
#ifdef PARANOID
|
||||
NUM_FOR_EDICT(ed); // make sure it's in range
|
||||
#endif
|
||||
errorif (!ed || ed->readonly)
|
||||
{ //boot it over to the debugger
|
||||
#if INTSIZE == 16
|
||||
ddef16_t *d = ED_GlobalAtOfs16(progfuncs, st->a);
|
||||
#else
|
||||
ddef32_t *d = ED_GlobalAtOfs32(progfuncs, st->a);
|
||||
#endif
|
||||
fdef_t *f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
|
||||
if (PR_ExecRunWarning(&progfuncs->funcs, st-pr_statements, "assignment to read-only entity %i in %s (%s.%s)\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), d?PR_StringToNative(&progfuncs->funcs, d->s_name):"??", f?f->name:"??"))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
|
||||
//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
|
||||
#ifdef NOLEGACY
|
||||
errorif (ed->ereftype == ER_FREE)
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "assignment to free entity in %s", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = OPB->_int + progfuncs->funcs.fieldadjust;
|
||||
errorif ((unsigned int)i*4 >= ed->fieldsize) //FIXME:lazy size check
|
||||
{
|
||||
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
|
||||
return prinst.pr_xstatement;
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = (eval_t *)(((int *)edvars(ed)) + i);
|
||||
ptr->_vector[0] = OPC->_vector[0];
|
||||
ptr->_vector[1] = OPC->_vector[1];
|
||||
ptr->_vector[2] = OPC->_vector[2];
|
||||
break;
|
||||
|
||||
|
||||
//get a pointer to a field var
|
||||
case OP_ADDRESS:
|
||||
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
|
||||
|
@ -828,7 +924,7 @@ reeval:
|
|||
case OP_LOADA_S:
|
||||
case OP_LOADA_FNC:
|
||||
i = st->a + OPB->_int;
|
||||
if ((size_t)(i<<2) >= (size_t)current_progstate->globals_size)
|
||||
if ((size_t)i >= (size_t)(current_progstate->globals_bytes>>2))
|
||||
{
|
||||
QCFAULT(&progfuncs->funcs, "bad array read in %s (index %i)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int);
|
||||
}
|
||||
|
@ -838,7 +934,7 @@ reeval:
|
|||
|
||||
case OP_LOADA_V:
|
||||
i = st->a + OPB->_int;
|
||||
if ((size_t)(i<<2) >= (size_t)current_progstate->globals_size)
|
||||
if ((size_t)(i) >= (size_t)(current_progstate->globals_bytes>>2)-2u)
|
||||
{
|
||||
QCFAULT(&progfuncs->funcs, "bad array read in %s (index %i)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int);
|
||||
}
|
||||
|
@ -1267,19 +1363,19 @@ reeval:
|
|||
case OP_GLOAD_ENT:
|
||||
case OP_GLOAD_S:
|
||||
case OP_GLOAD_FNC:
|
||||
errorif (OPA->_int < 0 || OPA->_int*4 >= current_progstate->globals_size)
|
||||
errorif (OPA->_int < 0 || OPA->_int >= (current_progstate->globals_bytes>>2))
|
||||
{
|
||||
prinst.pr_xstatement = st-pr_statements;
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPA->_int, current_progstate->globals_size);
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPA->_int, current_progstate->globals_bytes>>2);
|
||||
}
|
||||
ptr = ((eval_t *)&glob[OPA->_int]);
|
||||
OPC->_int = ptr->_int;
|
||||
break;
|
||||
case OP_GLOAD_V:
|
||||
errorif (OPA->_int < 0 || (OPA->_int+2)*4 >= current_progstate->globals_size)
|
||||
errorif (OPA->_int < 0 || OPA->_int >= (current_progstate->globals_bytes>>2)-2u)
|
||||
{
|
||||
prinst.pr_xstatement = st-pr_statements;
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPA->_int, current_progstate->globals_size);
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global read in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPA->_int, current_progstate->globals_bytes>>2);
|
||||
}
|
||||
ptr = ((eval_t *)&glob[OPA->_int]);
|
||||
OPC->_vector[0] = ptr->_vector[0];
|
||||
|
@ -1292,19 +1388,19 @@ reeval:
|
|||
case OP_GSTOREP_FLD:
|
||||
case OP_GSTOREP_S:
|
||||
case OP_GSTOREP_FNC:
|
||||
errorif (OPB->_int < 0 || OPB->_int*4 >= current_progstate->globals_size)
|
||||
errorif (OPB->_int < 0 || OPB->_int >= (current_progstate->globals_bytes>>2))
|
||||
{
|
||||
prinst.pr_xstatement = st-pr_statements;
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int, (unsigned)prinst.addressableused);
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int, current_progstate->globals_bytes>>2);
|
||||
}
|
||||
ptr = ((eval_t *)&glob[OPB->_int]);
|
||||
ptr->_int = OPA->_int;
|
||||
break;
|
||||
case OP_GSTOREP_V:
|
||||
errorif (OPB->_int < 0 || (OPB->_int+2)*4 >= current_progstate->globals_size)
|
||||
errorif (OPB->_int < 0 || OPB->_int >= (current_progstate->globals_bytes>>2)-2u)
|
||||
{
|
||||
prinst.pr_xstatement = st-pr_statements;
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int, (unsigned)prinst.addressableused);
|
||||
PR_RunError (&progfuncs->funcs, "bad indexed global write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int, current_progstate->globals_bytes>>2);
|
||||
}
|
||||
ptr = ((eval_t *)&glob[OPB->_int]);
|
||||
ptr->_vector[0] = OPA->_vector[0];
|
||||
|
|
|
@ -145,37 +145,37 @@ enum qcop_e {
|
|||
OP_SUBSTOREP_F, //78
|
||||
OP_SUBSTOREP_V, //79
|
||||
|
||||
OP_FETCH_GBL_F, //80
|
||||
OP_FETCH_GBL_V, //81
|
||||
OP_FETCH_GBL_S, //82
|
||||
OP_FETCH_GBL_E, //83
|
||||
OP_FETCH_GBL_FNC,//84
|
||||
OP_FETCH_GBL_F, //80 has built-in bounds check
|
||||
OP_FETCH_GBL_V, //81 has built-in bounds check
|
||||
OP_FETCH_GBL_S, //82 has built-in bounds check
|
||||
OP_FETCH_GBL_E, //83 has built-in bounds check
|
||||
OP_FETCH_GBL_FNC,//84 has built-in bounds check
|
||||
|
||||
OP_CSTATE, //85
|
||||
OP_CWSTATE, //86
|
||||
|
||||
OP_THINKTIME, //87
|
||||
OP_THINKTIME, //87 shortcut for OPA.nextthink=time+OPB
|
||||
|
||||
OP_BITSETSTORE_F, //88 redundant, for h2 compat
|
||||
OP_BITSETSTOREP_F, //89
|
||||
OP_BITCLRSTORE_F, //90
|
||||
OP_BITCLRSTOREP_F, //91
|
||||
|
||||
OP_RAND0, //92
|
||||
OP_RAND1, //93
|
||||
OP_RAND2, //94
|
||||
OP_RANDV0, //95
|
||||
OP_RAND0, //92 OPC = random()
|
||||
OP_RAND1, //93 OPC = random()*OPA
|
||||
OP_RAND2, //94 OPC = random()*(OPB-OPA)+OPA
|
||||
OP_RANDV0, //95 //3d/box versions of the above.
|
||||
OP_RANDV1, //96
|
||||
OP_RANDV2, //97
|
||||
|
||||
OP_SWITCH_F, //98
|
||||
OP_SWITCH_F, //98 switchref=OPA; PC += OPB --- the jump allows the jump table (such as it is) to be inserted after the block.
|
||||
OP_SWITCH_V, //99
|
||||
OP_SWITCH_S, //100
|
||||
OP_SWITCH_E, //101
|
||||
OP_SWITCH_FNC, //102
|
||||
|
||||
OP_CASE, //103
|
||||
OP_CASERANGE, //104
|
||||
OP_CASE, //103 if (OPA===switchref) PC += OPB
|
||||
OP_CASERANGE, //104 if (OPA<=switchref&&switchref<=OPB) PC += OPC
|
||||
|
||||
|
||||
|
||||
|
@ -184,9 +184,10 @@ enum qcop_e {
|
|||
//the rest are added
|
||||
//mostly they are various different ways of adding two vars with conversions.
|
||||
|
||||
OP_CALL1H,
|
||||
OP_CALL2H,
|
||||
OP_CALL3H,
|
||||
//hexen2 calling convention (-TH2 requires us to remap OP_CALLX to these on load, -TFTE just uses these directly.)
|
||||
OP_CALL1H, //OFS_PARM0=OPB
|
||||
OP_CALL2H, //OFS_PARM0,1=OPB,OPC
|
||||
OP_CALL3H, //no extra args
|
||||
OP_CALL4H,
|
||||
OP_CALL5H,
|
||||
OP_CALL6H, //110
|
||||
|
@ -195,21 +196,21 @@ enum qcop_e {
|
|||
|
||||
|
||||
OP_STORE_I,
|
||||
OP_STORE_IF,
|
||||
OP_STORE_FI,
|
||||
OP_STORE_IF, //OPB.f = (float)OPA.i (makes more sense when written as a->b)
|
||||
OP_STORE_FI, //OPB.i = (int)OPA.f
|
||||
|
||||
OP_ADD_I,
|
||||
OP_ADD_FI,
|
||||
OP_ADD_IF,
|
||||
OP_ADD_FI, //OPC.f = OPA.f + OPB.i
|
||||
OP_ADD_IF, //OPC.f = OPA.i + OPB.f -- redundant...
|
||||
|
||||
OP_SUB_I,
|
||||
OP_SUB_FI, //120
|
||||
OP_SUB_IF,
|
||||
OP_SUB_I, //OPC.i = OPA.i - OPB.i
|
||||
OP_SUB_FI, //120 //OPC.f = OPA.f - OPB.i
|
||||
OP_SUB_IF, //OPC.f = OPA.i - OPB.f
|
||||
|
||||
OP_CONV_ITOF,
|
||||
OP_CONV_FTOI,
|
||||
OP_CP_ITOF,
|
||||
OP_CP_FTOI,
|
||||
OP_CONV_ITOF, //OPC.f=(float)OPA.i
|
||||
OP_CONV_FTOI, //OPC.i=(int)OPA.f
|
||||
OP_CP_ITOF, //OPC.f=(float)(*OPA).i
|
||||
OP_CP_FTOI, //OPC.i=(int)(*OPA).f
|
||||
OP_LOAD_I,
|
||||
OP_STOREP_I,
|
||||
OP_STOREP_IF,
|
||||
|
@ -223,7 +224,7 @@ enum qcop_e {
|
|||
OP_EQ_I,
|
||||
OP_NE_I,
|
||||
|
||||
OP_IFNOT_S,
|
||||
OP_IFNOT_S, //compares string empty, rather than just null.
|
||||
OP_IF_S,
|
||||
|
||||
OP_NOT_I,
|
||||
|
@ -234,8 +235,8 @@ enum qcop_e {
|
|||
OP_RSHIFT_I,
|
||||
OP_LSHIFT_I,
|
||||
|
||||
OP_GLOBALADDRESS,
|
||||
OP_ADD_PIW, //add B words to A pointer
|
||||
OP_GLOBALADDRESS, //C.p = &A + B.i*4
|
||||
OP_ADD_PIW, //C.p = A.p + B.i*4
|
||||
|
||||
OP_LOADA_F,
|
||||
OP_LOADA_V,
|
||||
|
@ -302,7 +303,7 @@ enum qcop_e {
|
|||
OP_NE_IF,
|
||||
OP_NE_FI,
|
||||
|
||||
//erm... FTEQCC doesn't make use of these... These are for DP.
|
||||
//erm... FTEQCC doesn't make use of these (doesn't model separate pointer types). These are for DP.
|
||||
OP_GSTOREP_I,
|
||||
OP_GSTOREP_F,
|
||||
OP_GSTOREP_ENT,
|
||||
|
@ -326,10 +327,16 @@ enum qcop_e {
|
|||
|
||||
OP_SWITCH_I,//hmm.
|
||||
OP_GLOAD_V,
|
||||
|
||||
OP_IF_F,
|
||||
//r3349+
|
||||
OP_IF_F, //compares as an actual float, instead of treating -0 as positive.
|
||||
OP_IFNOT_F,
|
||||
|
||||
//r5697+
|
||||
OP_STOREF_V, //3 elements...
|
||||
OP_STOREF_F, //1 fpu element...
|
||||
OP_STOREF_S, //1 string reference
|
||||
OP_STOREF_I, //1 non-string reference/int
|
||||
|
||||
OP_NUMREALOPS,
|
||||
|
||||
/*
|
||||
|
|
|
@ -2097,8 +2097,8 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, void *ctx, void (PD
|
|||
|
||||
if (num == 0 && oldglobals)
|
||||
{
|
||||
if (pr_progstate[0].globals_size == oldglobalssize)
|
||||
memcpy(pr_progstate[0].globals, oldglobals, pr_progstate[0].globals_size);
|
||||
if (pr_progstate[0].globals_bytes == oldglobalssize)
|
||||
memcpy(pr_progstate[0].globals, oldglobals, pr_progstate[0].globals_bytes);
|
||||
free(oldglobals);
|
||||
oldglobals = NULL;
|
||||
}
|
||||
|
@ -2217,16 +2217,16 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, void *ctx, void (PD
|
|||
if (oldglobals)
|
||||
free(oldglobals);
|
||||
oldglobals = NULL;
|
||||
if (pr_progstate[0].globals_size)
|
||||
if (pr_progstate[0].globals_bytes)
|
||||
{
|
||||
oldglobals = malloc(pr_progstate[0].globals_size);
|
||||
oldglobals = malloc(pr_progstate[0].globals_bytes);
|
||||
if (oldglobals)
|
||||
{
|
||||
oldglobalssize = pr_progstate[0].globals_size;
|
||||
oldglobalssize = pr_progstate[0].globals_bytes;
|
||||
memcpy(oldglobals, pr_progstate[0].globals, oldglobalssize);
|
||||
}
|
||||
else
|
||||
externs->Printf("Unable to alloc %i bytes\n", pr_progstate[0].globals_size);
|
||||
externs->Printf("Unable to alloc %i bytes\n", pr_progstate[0].globals_bytes);
|
||||
}
|
||||
|
||||
PRAddressableFlush(progfuncs, 0);
|
||||
|
@ -2784,7 +2784,7 @@ retry:
|
|||
current_progstate->statements = (void *)((qbyte *)pr_progs + pr_progs->ofs_statements);
|
||||
|
||||
glob = pr_globals = (void *)((qbyte *)pr_progs + pr_progs->ofs_globals);
|
||||
current_progstate->globals_size = pr_progs->numglobals*sizeof(*pr_globals);
|
||||
current_progstate->globals_bytes = pr_progs->numglobals*sizeof(*pr_globals);
|
||||
|
||||
pr_linenums=NULL;
|
||||
pr_types=NULL;
|
||||
|
|
|
@ -351,7 +351,7 @@ typedef struct progstate_s
|
|||
// };
|
||||
// void *global_struct;
|
||||
float *globals; // same as pr_global_struct
|
||||
int globals_size; // in bytes
|
||||
unsigned int globals_bytes; // in bytes
|
||||
|
||||
typeinfo_t *types;
|
||||
|
||||
|
|
|
@ -655,12 +655,12 @@ QCC_opcode_t pr_opcodes[] =
|
|||
|
||||
{7, "<IF_F>", "IF_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void},
|
||||
{7, "<IFNOT_F>","IFNOT_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void},
|
||||
/*
|
||||
{7, "<=>", "STOREF_F", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
|
||||
{7, "<=>", "STOREF_V", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector},
|
||||
{7, "<=>", "STOREF_IF", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
|
||||
{7, "<=>", "STOREF_FI", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
|
||||
*/
|
||||
|
||||
{7, "<=>", "STOREF_V", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector},
|
||||
{7, "<=>", "STOREF_F", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
|
||||
{7, "<=>", "STOREF_S", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_string},
|
||||
{7, "<=>", "STOREF_I", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_integer},
|
||||
|
||||
/* emulated ops begin here */
|
||||
{7, "<>", "OP_EMULATED", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float},
|
||||
|
||||
|
@ -775,8 +775,8 @@ static pbool OpAssignsToC(unsigned int op)
|
|||
return false;
|
||||
if(op >= OP_SWITCH_F && op <= OP_CALL8H)
|
||||
return false;
|
||||
if(op >= OP_RAND0 && op <= OP_RANDV2)
|
||||
return false;
|
||||
// if(op >= OP_RAND0 && op <= OP_RANDV2)
|
||||
// return false;
|
||||
// they use a and b, but have 3 types
|
||||
// safety
|
||||
if(op >= OP_BITSETSTORE_F && op <= OP_BITCLRSTOREP_F)
|
||||
|
@ -791,6 +791,8 @@ static pbool OpAssignsToC(unsigned int op)
|
|||
return false; //actually they do.
|
||||
if (op >= OP_STORE_I && op <= OP_STORE_FI)
|
||||
return false;
|
||||
if (op >= OP_STOREF_V && op <= OP_STOREF_I)
|
||||
return false; //reads it, doesn't write.
|
||||
if (op == OP_BOUNDCHECK || op == OP_UNUSED || op == OP_POP)
|
||||
return false;
|
||||
return true;
|
||||
|
@ -847,6 +849,7 @@ static int OpAssignsCount(unsigned int op)
|
|||
case OP_RANDV0:
|
||||
case OP_RANDV1:
|
||||
case OP_RANDV2:
|
||||
return 1; //writes C, even when there's no A or B arg specified.
|
||||
case OP_UNUSED:
|
||||
case OP_POP:
|
||||
return 0; //FIXME
|
||||
|
@ -867,6 +870,11 @@ static int OpAssignsCount(unsigned int op)
|
|||
case OP_CASE:
|
||||
case OP_CASERANGE:
|
||||
return 0;
|
||||
case OP_STOREF_V:
|
||||
case OP_STOREF_F:
|
||||
case OP_STOREF_S:
|
||||
case OP_STOREF_I:
|
||||
return 0; //stores to a.b rather than any direct value...
|
||||
case OP_BOUNDCHECK:
|
||||
return 0;
|
||||
default: //the majority will write c
|
||||
|
@ -1182,6 +1190,8 @@ static pbool QCC_OPCodeValid(QCC_opcode_t *op)
|
|||
case QCF_FTEH2:
|
||||
case QCF_FTE:
|
||||
case QCF_FTEDEBUG:
|
||||
if (num >= OP_STOREF_V) //to be enabled at a later date - opcodes added in r5698.
|
||||
return false;
|
||||
return true;
|
||||
case QCF_DARKPLACES:
|
||||
//all id opcodes.
|
||||
|
@ -4957,7 +4967,9 @@ static void QCC_VerifyArgs_setviewprop (const char *funcname, QCC_ref_t **arglis
|
|||
{"VF_RT_DESTCOLOUR7", 219, ev_string, ev_float, ev_vector},
|
||||
{"VF_ENVMAP", 220, ev_string},
|
||||
{"VF_USERDATA", 221, ev_pointer, ev_integer},
|
||||
{"VF_SKYROOM_CAMERA", 222, ev_vector}
|
||||
{"VF_SKYROOM_CAMERA", 222, ev_vector},
|
||||
// {"VF_PIXELPSCALE", 223, ev_vector},
|
||||
{"VF_PROJECTIONOFFSET", 224, ev_vector},
|
||||
};
|
||||
|
||||
char temp[256];
|
||||
|
@ -5495,6 +5507,8 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
|
|||
|
||||
if (!strcmp(funcname, "strlen") && QCC_Intrinsic_strlen(&d, a))
|
||||
return d;
|
||||
if (!strcmp(funcname, "stof"))
|
||||
return QCC_MakeFloatConst(atof(&strings[a->string]));
|
||||
}
|
||||
}
|
||||
else if (opt_constantarithmatic && argcount == 2 && arglist[0]->type == REF_GLOBAL && arglist[1]->type == REF_GLOBAL)
|
||||
|
@ -5503,16 +5517,23 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
|
|||
const QCC_eval_t *b = QCC_SRef_EvalConst(arglist[1]->base);
|
||||
if (a && b)
|
||||
{
|
||||
if (!strcmp(funcname, "pow"))
|
||||
return QCC_MakeFloatConst(pow(a->_float, b->_float));
|
||||
if (!strcmp(funcname, "mod"))
|
||||
return QCC_MakeFloatConst(fmodf((int)a->_float, (int)b->_float));
|
||||
if (!strcmp(funcname, "bitshift"))
|
||||
if (arglist[0]->cast == type_float && arglist[1]->cast == type_float)
|
||||
{
|
||||
if (b->_float < 0)
|
||||
return QCC_MakeFloatConst((int)a->_float >> (int)-b->_float);
|
||||
else
|
||||
return QCC_MakeFloatConst((int)a->_float << (int)b->_float);
|
||||
if (!strcmp(funcname, "pow"))
|
||||
return QCC_MakeFloatConst(pow(a->_float, b->_float));
|
||||
if (!strcmp(funcname, "mod"))
|
||||
return QCC_MakeFloatConst(fmodf((int)a->_float, (int)b->_float));
|
||||
if (!strcmp(funcname, "min"))
|
||||
return QCC_MakeFloatConst(min(a->_float, b->_float));
|
||||
if (!strcmp(funcname, "max"))
|
||||
return QCC_MakeFloatConst(max(a->_float, b->_float));
|
||||
if (!strcmp(funcname, "bitshift"))
|
||||
{
|
||||
if (b->_float < 0)
|
||||
return QCC_MakeFloatConst((int)a->_float >> (int)-b->_float);
|
||||
else
|
||||
return QCC_MakeFloatConst((int)a->_float << (int)b->_float);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5624,6 +5645,7 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
|
|||
copyop_i = OP_LOADA_F;
|
||||
copyop_idx = -1;
|
||||
copyop_index = arglist[i]->index;
|
||||
copyop_index = QCC_SupplyConversion(copyop_index, ev_integer, true);
|
||||
sref = arglist[i]->base;
|
||||
}
|
||||
else if (arglist[i]->base.sym->arraylengthprefix && QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F]))
|
||||
|
@ -9690,15 +9712,53 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
QCC_PR_ParseErrorPrintSRef(ERR_NOFUNC, dest->base, "Accessor has no set function");
|
||||
break;
|
||||
case REF_FIELD:
|
||||
// {
|
||||
{
|
||||
int storef_opcode;
|
||||
//fixme: we should do this earlier, to preserve original instruction ordering.
|
||||
//such that self.enemy = (self = world); still has the same result (more common with function calls)
|
||||
|
||||
dest = QCC_PR_BuildRef(&ptrref, REF_POINTER,
|
||||
QCC_PR_StatementFlags(&pr_opcodes[OP_ADDRESS], dest->base, dest->index, NULL, preservedest?STFL_PRESERVEA:0), //pointer address
|
||||
nullsref, (dest->index.cast->type == ev_field)?dest->index.cast->aux_type:type_variant, dest->readonly);
|
||||
preservedest = false;
|
||||
continue;
|
||||
|
||||
if (dest->cast->type == ev_float)
|
||||
storef_opcode = OP_STOREF_F;
|
||||
else if (dest->cast->type == ev_vector)
|
||||
storef_opcode = OP_STOREF_V;
|
||||
else if (dest->cast->type == ev_string)
|
||||
storef_opcode = OP_STOREF_S;
|
||||
else if ( dest->cast->type == ev_entity ||
|
||||
dest->cast->type == ev_field ||
|
||||
dest->cast->type == ev_function ||
|
||||
dest->cast->type == ev_pointer ||
|
||||
dest->cast->type == ev_integer)
|
||||
storef_opcode = OP_STOREF_I;
|
||||
else
|
||||
storef_opcode = OP_DONE;
|
||||
//don't use it for arrays. address+storep_with_offset is less opcodes.
|
||||
if (storef_opcode!=OP_DONE && dest->cast->size == 1 && QCC_OPCodeValid(&pr_opcodes[storef_opcode]))
|
||||
{
|
||||
dest->base.sym->referenced = true;
|
||||
dest->index.sym->referenced = true;
|
||||
source.sym->referenced = true;
|
||||
//doesn't generate any temps.
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[storef_opcode], dest->base, dest->index, source, true);
|
||||
|
||||
if (!preservedest)
|
||||
{
|
||||
QCC_FreeTemp(dest->base);
|
||||
QCC_FreeTemp(dest->index);
|
||||
}
|
||||
if (!readable)
|
||||
{
|
||||
QCC_FreeTemp(source);
|
||||
source = nullsref;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = QCC_PR_BuildRef(&ptrref, REF_POINTER,
|
||||
QCC_PR_StatementFlags(&pr_opcodes[OP_ADDRESS], dest->base, dest->index, NULL, preservedest?STFL_PRESERVEA:0), //pointer address
|
||||
nullsref, (dest->index.cast->type == ev_field)?dest->index.cast->aux_type:type_variant, dest->readonly);
|
||||
preservedest = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// source = QCC_StoreToRef(
|
||||
// QCC_PR_BuildRef(&tmp, REF_POINTER,
|
||||
|
@ -9706,8 +9766,8 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
// NULL, (dest->index->type->type == ev_field)?dest->index->type->aux_type:type_variant, dest->readonly),
|
||||
// source, readable, false);
|
||||
// QCC_PR_ParseWarning(ERR_INTERNAL, "FIXME: trying to do references: assignments to ent.field not supported.\n");
|
||||
// }
|
||||
// break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -12485,7 +12545,7 @@ static int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_
|
|||
return i;
|
||||
}
|
||||
}
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->a.ofs > 0)
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->a.ofs > 0 && !st->a.sym)
|
||||
{
|
||||
int jump = i + (int)st->a.ofs;
|
||||
ret = QCC_CheckOneUninitialised(i + 1, jump, def, min, max);
|
||||
|
@ -12504,7 +12564,7 @@ static int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_
|
|||
return i;
|
||||
}
|
||||
}
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->b.ofs > 0 && !(st->flags & STF_LOGICOP))
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->b.ofs > 0 && !st->b.sym && !(st->flags & STF_LOGICOP))
|
||||
{
|
||||
int jump = i + (int)st->b.ofs;
|
||||
//check if there's an else.
|
||||
|
@ -12539,7 +12599,7 @@ static int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_
|
|||
|
||||
return i;
|
||||
}
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->c.ofs > 0)
|
||||
else if (pr_opcodes[st->op].associative == ASSOC_RIGHT && (int)st->c.ofs > 0 && !st->c.sym)
|
||||
{
|
||||
int jump = i + (int)st->c.ofs;
|
||||
ret = QCC_CheckOneUninitialised(i + 1, jump, def, min, max);
|
||||
|
|
|
@ -1330,14 +1330,17 @@ static pbool QCC_PR_Precompiler(void)
|
|||
else if (!QC_strcasecmp(qcc_token, "KK7"))
|
||||
newtype = QCF_KK7;
|
||||
else if (!QC_strcasecmp(qcc_token, "DP") || !QC_strcasecmp(qcc_token, "DARKPLACES"))
|
||||
{
|
||||
QCC_PR_ParseWarning(WARN_BADTARGET, "#pragma target \"%s\". Requires an unofficial patch to DP. Without that patch there is no support for any opcodes beyond vanilla.", qcc_token);
|
||||
newtype = QCF_DARKPLACES;
|
||||
}
|
||||
else if (!QC_strcasecmp(qcc_token, "FTEDEBUG"))
|
||||
newtype = QCF_FTEDEBUG;
|
||||
else if (!QC_strcasecmp(qcc_token, "FTE"))
|
||||
newtype = QCF_FTE;
|
||||
else if (!QC_strcasecmp(qcc_token, "FTEH2"))
|
||||
newtype = QCF_FTEH2;
|
||||
else if (!QC_strcasecmp(qcc_token, "STANDARD") || !QC_strcasecmp(qcc_token, "ID"))
|
||||
else if (!QC_strcasecmp(qcc_token, "STANDARD") || !QC_strcasecmp(qcc_token, "ID") || !QC_strcasecmp(qcc_token, "VANILLA"))
|
||||
newtype = QCF_STANDARD;
|
||||
else if (!QC_strcasecmp(qcc_token, "DEBUG"))
|
||||
newtype = QCF_FTEDEBUG;
|
||||
|
|
|
@ -1200,6 +1200,18 @@ public:
|
|||
return NULL;//"Type info not available. Compile first.";
|
||||
}
|
||||
|
||||
void clearannotates(void)
|
||||
{
|
||||
for (int i = 0; i < numdocuments; i++)
|
||||
{
|
||||
document_s *d = docs[i];
|
||||
s->setDocument(d->doc);
|
||||
s->clearAnnotations();
|
||||
}
|
||||
if (curdoc)
|
||||
s->setDocument(curdoc->doc);
|
||||
}
|
||||
|
||||
bool annotate(const char *line)
|
||||
{
|
||||
auto filename = line+6;
|
||||
|
@ -2292,6 +2304,8 @@ int GUIprintf(const char *msg, ...)
|
|||
sizes.append(1);
|
||||
mainwnd->logsplit.setSizes(sizes);
|
||||
}
|
||||
|
||||
mainwnd->docs.clearannotates();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ int main (int argc, const char **argv)
|
|||
{
|
||||
unsigned int i;
|
||||
pbool sucess;
|
||||
#ifdef _WIN32
|
||||
#if 0//def _WIN32
|
||||
pbool writelog = true; //spew log files on windows. windows often closes the window as soon as the program ends making its output otherwise unreadable.
|
||||
#else
|
||||
pbool writelog = false; //other systems are sane.
|
||||
|
|
Loading…
Reference in a new issue