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:
Spoike 2020-05-30 12:12:46 +00:00
parent df5b4e4e48
commit 62a4572f23
8 changed files with 263 additions and 83 deletions

View file

@ -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];

View file

@ -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,
/*

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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.