Try to fix the bugs that Paril found... I wonder if I broke anything new.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5723 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
c09cf1481a
commit
82ecdfbfa8
6 changed files with 293 additions and 89 deletions
|
@ -251,6 +251,9 @@ reeval:
|
|||
case OP_NOT_ENT:
|
||||
OPC->_float = (float)(!(OPA->edict));//(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts);
|
||||
break;
|
||||
case OP_NOT_I:
|
||||
OPC->_int = !OPA->_int;
|
||||
break;
|
||||
|
||||
case OP_EQ_F:
|
||||
OPC->_float = (float)(OPA->_float == OPB->_float);
|
||||
|
@ -1351,10 +1354,6 @@ reeval:
|
|||
OPC->_int = (OPA->_float || OPB->_int);
|
||||
break;
|
||||
|
||||
case OP_NOT_I:
|
||||
OPC->_int = !OPA->_int;
|
||||
break;
|
||||
|
||||
case OP_NE_IF:
|
||||
OPC->_int = (OPA->_int != OPB->_float);
|
||||
break;
|
||||
|
|
|
@ -383,6 +383,7 @@ typedef struct QCC_type_s
|
|||
struct accessor_s *accessors;
|
||||
|
||||
struct QCC_type_s *ptrto; //(cache) this points to a type that is a pointer back to this type. yeah, weird.
|
||||
struct QCC_type_s *fldto; //(cache) this points to a type that is a pointer back to this type. yeah, weird.
|
||||
} QCC_type_t;
|
||||
int typecmp(QCC_type_t *a, QCC_type_t *b);
|
||||
int typecmp_lax(QCC_type_t *a, QCC_type_t *b);
|
||||
|
|
|
@ -222,6 +222,7 @@ void QCC_PR_DiscardRef(QCC_ref_t *ref);
|
|||
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type, pbool dowrap);
|
||||
const char *QCC_VarAtOffset(QCC_sref_t ref);
|
||||
QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit);
|
||||
QCC_sref_t QCC_PR_ParseInitializerTemp(QCC_type_t *type);
|
||||
pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags);
|
||||
#define PIF_WRAP 1 //new initialisation is meant to wrap an existing one.
|
||||
#define PIF_STRONGER 2 //previous initialisation was weak.
|
||||
|
@ -255,7 +256,8 @@ enum
|
|||
STFL_CONVERTA=1u<<1, //convert to/from ints/floats to match the operand types required by the opcode
|
||||
STFL_PRESERVEB=1u<<2,
|
||||
STFL_CONVERTB=1u<<3,
|
||||
STFL_DISCARDRESULT=1u<<4
|
||||
STFL_DISCARDRESULT=1u<<4,
|
||||
STFL_NOEMULATE=1u<<5, //don't emulate unsupported opcode with other opcodes.
|
||||
};
|
||||
#define QCC_PR_Statement(op,a,b,st) QCC_PR_StatementFlags(op,a,b,st,STFL_CONVERTA|STFL_CONVERTB)
|
||||
QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_t var_b, QCC_statement_t **outstatement, unsigned int flags);
|
||||
|
@ -2067,7 +2069,10 @@ const char *QCC_VarAtOffset(QCC_sref_t ref)
|
|||
{
|
||||
if (ref.sym && ref.sym->temp)
|
||||
{
|
||||
QC_snprintfz(message, sizeof(message), "temp_%i+%i", ref.sym->ofs-tempsinfo[0].def->ofs, ref.ofs);
|
||||
if (!ref.ofs)
|
||||
QC_snprintfz(message, sizeof(message), "temp_%i", ref.sym->ofs-tempsinfo[0].def->ofs);
|
||||
else
|
||||
QC_snprintfz(message, sizeof(message), "temp_%i+%i", ref.sym->ofs-tempsinfo[0].def->ofs, ref.ofs);
|
||||
return message;
|
||||
}
|
||||
else if (ref.sym->name && !STRCMP(ref.sym->name, "IMMEDIATE"))
|
||||
|
@ -2141,13 +2146,19 @@ const char *QCC_VarAtOffset(QCC_sref_t ref)
|
|||
QC_snprintfz(message, sizeof(message), "'%g %g %g'", val->vector[0], val->vector[1], val->vector[2]);
|
||||
return message;
|
||||
default:
|
||||
QC_snprintfz(message, sizeof(message), "IMMEDIATE");
|
||||
if (!ref.ofs)
|
||||
QC_snprintfz(message, sizeof(message), "IMMEDIATE");
|
||||
else
|
||||
QC_snprintfz(message, sizeof(message), "IMMEDIATE+%i", ref.ofs);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
else if (ref.ofs || ref.cast != ref.sym->type)
|
||||
{
|
||||
QC_snprintfz(message, sizeof(message), "%s+%i", ref.sym->name, ref.ofs);
|
||||
if (!ref.ofs)
|
||||
QC_snprintfz(message, sizeof(message), "%s", ref.sym->name);
|
||||
else
|
||||
QC_snprintfz(message, sizeof(message), "%s+%i", ref.sym->name, ref.ofs);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -3118,7 +3129,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
}
|
||||
}
|
||||
|
||||
if (!QCC_OPCodeValid(op))
|
||||
if (!QCC_OPCodeValid(op) && !(flags&STFL_NOEMULATE))
|
||||
{
|
||||
QCC_sref_t tmp;
|
||||
//FIXME: add support for flags so we don't corrupt temps
|
||||
|
@ -3455,6 +3466,24 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_F], var_b, var_a, NULL, 0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_c, var_a, NULL, 0);
|
||||
|
||||
case OP_BITXOR_I:
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "BitxorInt", NULL, false, 0, 0);
|
||||
if (!fnc.cast)
|
||||
{
|
||||
QCC_PR_ParseError(0, "BitxorInt function not defined: cannot emulate int^int");
|
||||
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITNOT_I], var_b, nullsref, NULL, STFL_PRESERVEA);
|
||||
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_I], var_a, var_c, NULL, STFL_PRESERVEA);
|
||||
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_BITNOT_I], var_a, nullsref, NULL, 0);
|
||||
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_I], var_b, var_a, NULL, 0);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_I], var_c, var_a, NULL, 0);
|
||||
}
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
|
||||
var_c.cast = type_integer;
|
||||
return var_c;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_BITXOR_V:
|
||||
// r = (a & ~b) | (b & ~a);
|
||||
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITNOT_V], var_b, nullsref, NULL, STFL_PRESERVEA);
|
||||
|
@ -3543,9 +3572,22 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
|
||||
case OP_BITNOT_I:
|
||||
op = &pr_opcodes[OP_SUB_I];
|
||||
var_b = var_a;
|
||||
var_a = QCC_MakeIntConst(~0);
|
||||
var_a.sym->referenced = true;
|
||||
if (QCC_OPCodeValid(op))
|
||||
{
|
||||
op = &pr_opcodes[OP_SUB_I];
|
||||
var_b = var_a;
|
||||
var_a = QCC_MakeIntConst(~0);
|
||||
var_a.sym->referenced = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "SubInt", NULL, false, 0, 0);
|
||||
if (!fnc.cast)
|
||||
QCC_PR_ParseError(0, "SubInt function not defined: cannot emulate ~int");
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
|
||||
var_c.cast = type_integer;
|
||||
return var_c;
|
||||
}
|
||||
break;
|
||||
case OP_BITNOT_F:
|
||||
op = &pr_opcodes[OP_SUB_F];
|
||||
|
@ -3915,6 +3957,27 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
|
||||
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, flags&STFL_PRESERVEB);
|
||||
|
||||
case OP_LSHIFT_I:
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "LShiftInt", NULL, false, 0, 0);
|
||||
if (!fnc.cast)
|
||||
QCC_PR_ParseError(0, "LShiftInt function not defined: cannot emulate int<<int");
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
|
||||
var_c.cast = type_integer;
|
||||
return var_c;
|
||||
}
|
||||
break;
|
||||
case OP_RSHIFT_I:
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "RShiftInt", NULL, false, 0, 0);
|
||||
if (!fnc.cast)
|
||||
QCC_PR_ParseError(0, "RShiftInt function not defined: cannot emulate int>>int");
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
|
||||
var_c.cast = type_integer;
|
||||
return var_c;
|
||||
}
|
||||
break;
|
||||
|
||||
//convert both to ints
|
||||
case OP_LSHIFT_F:
|
||||
if (QCC_OPCodeValid(&pr_opcodes[OP_LSHIFT_I]))
|
||||
|
@ -5334,9 +5397,9 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
|
|||
{
|
||||
QCC_sref_t r;
|
||||
c = QCC_PR_InlineFindDef(ctx, st->c, true);
|
||||
r = QCC_PR_StatementFlags(&pr_opcodes[st->op], a, b, NULL, 0);
|
||||
r = QCC_PR_StatementFlags(&pr_opcodes[st->op], a, b, NULL, STFL_NOEMULATE);
|
||||
if (c.cast && !QCC_SRef_EvalConst(r))
|
||||
c = QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_ENT], r, c, NULL, 0);
|
||||
c = QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_ENT], r, c, NULL, STFL_NOEMULATE);
|
||||
else
|
||||
{
|
||||
QCC_FreeTemp(c);
|
||||
|
@ -5388,15 +5451,16 @@ static QCC_sref_t QCC_PR_Inline(QCC_sref_t fdef, QCC_ref_t **arglist, unsigned i
|
|||
unsigned int a;
|
||||
const QCC_eval_t *eval = QCC_SRef_EvalConst(fdef);
|
||||
//make sure that its a function type and that there's no special weirdness
|
||||
if (!eval || fdef.cast != fdef.sym->type || eval->function < 0 || argcount > 8 || eval->function >= numfunctions || fdef.sym->arraysize != 0 || fdef.cast->type != ev_function || argcount != fdef.cast->num_parms || fdef.cast->vargs || fdef.cast->vargcount)
|
||||
if (!eval || eval->function < 0 || argcount > 8 || eval->function >= numfunctions || fdef.sym->arraysize != 0 || fdef.cast->type != ev_function || argcount != fdef.cast->num_parms || fdef.cast->vargs || fdef.cast->vargcount)
|
||||
return nullsref;
|
||||
ctx.func = &functions[eval->function];
|
||||
if (fdef.cast != ctx.func->type)
|
||||
return nullsref;
|
||||
|
||||
ctx.numlocals = 0;
|
||||
for (a = 0; a < argcount; a++)
|
||||
ctx.arglist[a] = QCC_RefToDef(arglist[a], true);
|
||||
ctx.fdef = fdef.sym;
|
||||
ctx.result = nullsref;
|
||||
ctx.func = &functions[eval->function];
|
||||
if ((int)ctx.func->code <= 0)
|
||||
{
|
||||
char *fname = ctx.func->name;
|
||||
|
@ -7277,6 +7341,33 @@ static QCC_sref_t QCC_PR_ExpandField(QCC_sref_t ent, QCC_sref_t field, QCC_type_
|
|||
//FIXME: class.staticmember should directly read staticmember instead of trying to dereference
|
||||
switch(fieldtype->type)
|
||||
{
|
||||
case ev_struct:
|
||||
case ev_union:
|
||||
case ev_enum:
|
||||
{
|
||||
int i;
|
||||
QCC_type_t *type = fieldtype;
|
||||
QCC_sref_t dest = QCC_GetTemp(type);
|
||||
QCC_sref_t source = field;
|
||||
//don't bother trying to optimise any temps here, its not likely to happen anyway.
|
||||
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOAD_V], ent, source, dest, false);
|
||||
for (; i < type->size; i++, dest.ofs++, source.ofs++)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOAD_F], ent, source, dest, false);
|
||||
source.ofs -= type->size;
|
||||
dest.ofs -= type->size;
|
||||
if (!(preserveflags & STFL_PRESERVEA))
|
||||
QCC_FreeTemp(ent);
|
||||
if (!(preserveflags & STFL_PRESERVEB))
|
||||
QCC_FreeTemp(field);
|
||||
|
||||
QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "QCC_PR_ExpandField: inefficient");
|
||||
return dest;
|
||||
}
|
||||
break;
|
||||
case ev_void:
|
||||
case ev_accessor:
|
||||
case ev_boolean:
|
||||
default:
|
||||
QCC_PR_ParseErrorPrintSRef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
|
||||
r = field;
|
||||
|
@ -8617,7 +8708,7 @@ static QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
|
|||
QCC_PR_ParseErrorPrintSRef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type.");
|
||||
}
|
||||
if (flag_qccx && QCC_PR_CheckToken ("@"))
|
||||
{
|
||||
{ //@foo is equivelent to (string)*(int*)&foo
|
||||
r = QCC_PR_RefExpression (retbuf, UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
if (r->cast->type == ev_float || r->cast->type == ev_integer)
|
||||
{
|
||||
|
@ -8698,8 +8789,9 @@ static QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
|
|||
}
|
||||
else
|
||||
{
|
||||
e = QCC_GetTemp(newtype);
|
||||
QCC_PR_ParseInitializerType(0, NULL, e, 0);
|
||||
e = QCC_PR_ParseInitializerTemp(newtype);
|
||||
if (newtype->type == ev_function && QCC_PR_PeekToken("("))
|
||||
e.sym->allowinline = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -8857,15 +8949,21 @@ static void QCC_StoreToSRef(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *type
|
|||
case ev_union:
|
||||
case ev_enum:
|
||||
//don't bother trying to optimise any temps here, its not likely to happen anyway.
|
||||
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
|
||||
if (QCC_SRef_IsNull(source))
|
||||
{
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_V], source, dest, nullsref, false);
|
||||
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_V], QCC_MakeVectorConst(0,0,0), dest, nullsref, false);
|
||||
for (; i < type->size; i++, dest.ofs++)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_F], QCC_MakeIntConst(0), dest, nullsref, false);
|
||||
}
|
||||
for (; i < type->size; i++, dest.ofs++, source.ofs++)
|
||||
else
|
||||
{
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_F], source, dest, nullsref, false);
|
||||
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_V], source, dest, nullsref, false);
|
||||
for (; i < type->size; i++, dest.ofs++, source.ofs++)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STORE_F], source, dest, nullsref, false);
|
||||
source.ofs -= type->size;
|
||||
}
|
||||
source.ofs -= type->size;
|
||||
dest.ofs -= type->size;
|
||||
if (!preservesource)
|
||||
QCC_FreeTemp(source);
|
||||
|
@ -8955,9 +9053,14 @@ static void QCC_StoreToPointer(QCC_sref_t dest, QCC_sref_t idx, QCC_sref_t sourc
|
|||
for (i = 0; i+2 < type->size; i+=3)
|
||||
{
|
||||
QCC_sref_t newidx = idx.sym?QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_I], idx, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA):QCC_MakeIntConst(i);
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, newidx, false);
|
||||
if (QCC_SRef_IsNull(source))
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], QCC_MakeVectorConst(0,0,0), dest, newidx, false);
|
||||
else
|
||||
{
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, newidx, false);
|
||||
source.ofs += 3;
|
||||
}
|
||||
QCC_FreeTemp(newidx);
|
||||
source.ofs += 3;
|
||||
}
|
||||
for (; i < type->size; i++)
|
||||
{
|
||||
|
@ -8972,16 +9075,26 @@ static void QCC_StoreToPointer(QCC_sref_t dest, QCC_sref_t idx, QCC_sref_t sourc
|
|||
for (i = 0; i+2 < type->size; i+=3)
|
||||
{
|
||||
QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA);
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, newptr, idx, false);
|
||||
if (QCC_SRef_IsNull(source))
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], QCC_MakeVectorConst(0,0,0), newptr, idx, false);
|
||||
else
|
||||
{
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, newptr, idx, false);
|
||||
source.ofs += 3;
|
||||
}
|
||||
QCC_FreeTemp(newptr);
|
||||
source.ofs += 3;
|
||||
}
|
||||
for (; i < type->size; i++)
|
||||
{
|
||||
QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA);
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, newptr, idx, false);
|
||||
if (QCC_SRef_IsNull(source))
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], QCC_MakeIntConst(0), newptr, idx, false);
|
||||
else
|
||||
{
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, newptr, idx, false);
|
||||
source.ofs += 1;
|
||||
}
|
||||
QCC_FreeTemp(newptr);
|
||||
source.ofs += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9578,6 +9691,7 @@ QCC_sref_t QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
|
|||
QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable, pbool preservedest)
|
||||
{
|
||||
QCC_ref_t ptrref;
|
||||
pbool nullsrc = QCC_SRef_IsNull(source);
|
||||
if (dest->readonly)
|
||||
{
|
||||
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", QCC_GetSRefName(dest->base));
|
||||
|
@ -9586,16 +9700,21 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
QCC_PR_ParsePrintSRef(WARN_ASSIGNMENTTOCONSTANT, dest->index);
|
||||
}
|
||||
|
||||
if (QCC_SRef_IsNull(source))
|
||||
{
|
||||
if (dest->cast->type == ev_vector)
|
||||
if (!nullsrc)
|
||||
/*{
|
||||
if (dest->cast->type == ev_struct || dest->cast->type == ev_union)
|
||||
{
|
||||
QCC_FreeTemp(source);
|
||||
source = QCC_MakeIntConst(0);
|
||||
}
|
||||
else if (dest->cast->type == ev_vector)
|
||||
{
|
||||
QCC_FreeTemp(source);
|
||||
source = QCC_MakeVectorConst(0, 0, 0);
|
||||
}
|
||||
source.cast = dest->cast;
|
||||
}
|
||||
else
|
||||
else*/
|
||||
{
|
||||
QCC_type_t *t = source.cast;
|
||||
while(t)
|
||||
|
@ -9740,6 +9859,10 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
//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->base.sym->referenced = true;
|
||||
dest->index.sym->referenced = true;
|
||||
source.sym->referenced = true;
|
||||
|
||||
if (dest->cast->type == ev_float)
|
||||
storef_opcode = OP_STOREF_F;
|
||||
else if (dest->cast->type == ev_vector)
|
||||
|
@ -9750,29 +9873,75 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
dest->cast->type == ev_field ||
|
||||
dest->cast->type == ev_function ||
|
||||
dest->cast->type == ev_pointer ||
|
||||
dest->cast->type == ev_integer)
|
||||
dest->cast->type == ev_integer ||
|
||||
dest->cast->type == ev_struct ||
|
||||
dest->cast->type == ev_union ||
|
||||
dest->cast->type == ev_enum)
|
||||
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]))
|
||||
if (storef_opcode!=OP_DONE && dest->index.cast->size == dest->cast->size && 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);
|
||||
int sz = dest->cast->size, i;
|
||||
if (nullsrc)
|
||||
{
|
||||
for (i = 0; i+2 < sz; i+=3, dest->index.ofs += 3)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREF_V], dest->base, dest->index, QCC_MakeVectorConst(0,0,0), true);
|
||||
for (; i < sz; i++, dest->index.ofs++)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[storef_opcode], dest->base, dest->index, QCC_MakeIntConst(0), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i+2 < sz; i+=3, dest->index.ofs += 3, source.ofs += 3)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREF_V], dest->base, dest->index, source, true);
|
||||
for (; i < sz; i++, dest->index.ofs++, source.ofs++)
|
||||
QCC_PR_SimpleStatement(&pr_opcodes[storef_opcode], dest->base, dest->index, source, true);
|
||||
source.ofs -= i;
|
||||
}
|
||||
dest->index.ofs -= i;
|
||||
if (!readable)
|
||||
{
|
||||
QCC_FreeTemp(source);
|
||||
source = nullsref;
|
||||
}
|
||||
|
||||
if (!preservedest)
|
||||
{
|
||||
QCC_FreeTemp(dest->base);
|
||||
QCC_FreeTemp(dest->index);
|
||||
}
|
||||
}
|
||||
else if (1)//dest->cast->type >= ev_variant)
|
||||
{
|
||||
QCC_sref_t t;
|
||||
int sz = dest->cast->size, i;
|
||||
for (i = 0; i+2 < sz; i+=3, dest->index.ofs += 3, source.ofs+=3)
|
||||
{
|
||||
t = QCC_PR_StatementFlags(&pr_opcodes[OP_ADDRESS], dest->base, dest->index, NULL, STFL_PRESERVEA|STFL_PRESERVEB);
|
||||
QCC_StoreToPointer(t, nullsref, nullsrc?QCC_MakeVectorConst(0,0,0):source, type_vector);
|
||||
QCC_FreeTemp(t);
|
||||
}
|
||||
for (; i < sz; i++, dest->index.ofs++, source.ofs++)
|
||||
{
|
||||
t = QCC_PR_StatementFlags(&pr_opcodes[OP_ADDRESS], dest->base, dest->index, NULL, STFL_PRESERVEA|STFL_PRESERVEB);
|
||||
QCC_StoreToPointer(t, nullsref, nullsrc?QCC_MakeFloatConst(0):source, (dest->cast->size!=1)?type_float:dest->cast);
|
||||
QCC_FreeTemp(t);
|
||||
}
|
||||
source.ofs -= i;
|
||||
dest->index.ofs -= i;
|
||||
|
||||
if (!readable)
|
||||
{
|
||||
QCC_FreeTemp(source);
|
||||
source = nullsref;
|
||||
}
|
||||
if (!preservedest)
|
||||
{
|
||||
QCC_FreeTemp(dest->base);
|
||||
QCC_FreeTemp(dest->index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -9782,13 +9951,6 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
preservedest = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// source = QCC_StoreToRef(
|
||||
// QCC_PR_BuildRef(&tmp, REF_POINTER,
|
||||
// QCC_PR_StatementFlags(&pr_opcodes[OP_ADDRESS], dest->base, dest->index, NULL, preservedest?STFL_PRESERVEA:0), //pointer address
|
||||
// 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;
|
||||
}
|
||||
|
@ -10268,6 +10430,12 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
ops_ptr = opcodes_divstorep;
|
||||
opname = "/=";
|
||||
}
|
||||
else
|
||||
{
|
||||
ops = NULL;
|
||||
ops_ptr = NULL;
|
||||
opname = NULL;
|
||||
}
|
||||
|
||||
if (ops)
|
||||
{
|
||||
|
@ -10286,6 +10454,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
if (conditional&1)
|
||||
QCC_PR_ParseWarning(WARN_ASSIGNMENTINCONDITIONAL, "suggest parenthesis for assignment used as truth value");
|
||||
|
||||
//FIXME: if this is a simple store, rhsr->type == REF_FIELD, and lhsd is a simple def, then we should just expand the field directly to the lhsd for more effient .structs
|
||||
rhsd = QCC_RefToDef(rhsr, true);
|
||||
|
||||
if (ops_ptr && (lhsr->type == REF_FIELD || lhsr->type == REF_POINTER))
|
||||
|
@ -10363,7 +10532,8 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
else */if (QCC_SRef_IsNull(rhsd))
|
||||
{
|
||||
QCC_FreeTemp(rhsd);
|
||||
if (lhsr->cast->type == ev_vector)
|
||||
rhsd = QCC_MakeIntConst(0);
|
||||
/*if (lhsr->cast->type == ev_vector)
|
||||
rhsd = QCC_MakeVectorConst(0,0,0);
|
||||
else if (lhsr->cast->type == ev_struct || lhsr->cast->type == ev_union)
|
||||
{
|
||||
|
@ -10375,7 +10545,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
rhsd = QCC_MakeIntConst(0);
|
||||
else
|
||||
rhsd = QCC_MakeIntConst(0);
|
||||
rhsd.cast = lhsr->cast;
|
||||
rhsd.cast = lhsr->cast;*/
|
||||
}
|
||||
else
|
||||
rhsd = QCC_SupplyConversionForAssignment(lhsr, rhsd, lhsr->cast, true);
|
||||
|
@ -12069,11 +12239,17 @@ void QCC_PR_ParseAsm(void)
|
|||
else
|
||||
a=nullsref;
|
||||
if (pr_opcodes[op].type_b != &type_void)
|
||||
{
|
||||
QCC_PR_CheckToken(",");
|
||||
b = QCC_PR_ParseValue(pr_classtype, false, false, true);
|
||||
}
|
||||
else
|
||||
b=nullsref;
|
||||
if (pr_opcodes[op].associative==ASSOC_LEFT && pr_opcodes[op].type_c != &type_void)
|
||||
{
|
||||
QCC_PR_CheckToken(",");
|
||||
c = QCC_PR_ParseValue(pr_classtype, false, false, true);
|
||||
}
|
||||
else
|
||||
c=nullsref;
|
||||
|
||||
|
@ -13637,10 +13813,11 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
|
|||
// QCC_sref_t fasttrackpossible = nullsref;
|
||||
int numslots;
|
||||
|
||||
if (thearray.cast->type == ev_vector)
|
||||
numslots = thearray.sym->arraysize;
|
||||
else
|
||||
numslots = thearray.sym->arraysize*thearray.cast->size;
|
||||
numslots = thearray.sym->arraysize;
|
||||
if (!numslots)
|
||||
numslots = 1;
|
||||
if (thearray.cast->type != ev_vector)
|
||||
numslots *= thearray.cast->size;
|
||||
|
||||
// if (flag_fasttrackarrays && numslots > 6)
|
||||
// fasttrackpossible = QCC_PR_GetSRef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
|
||||
|
@ -14622,8 +14799,10 @@ static pbool QCC_PR_GenerateInitializerType(QCC_def_t *basedef, QCC_sref_t tmp,
|
|||
else
|
||||
{
|
||||
QCC_sref_t rhs;
|
||||
pbool nullsource;
|
||||
finalnotconst:
|
||||
rhs = tmp;
|
||||
nullsource = QCC_SRef_IsNull(rhs);
|
||||
if (def.sym->initialized)
|
||||
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "%s initialised twice", basedef->name);
|
||||
|
||||
|
@ -14635,17 +14814,20 @@ finalnotconst:
|
|||
rhs.cast = def.cast = type_vector;
|
||||
if (type->size - i == 3)
|
||||
{
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_V], rhs, def, NULL, STFL_PRESERVEB));
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_V], nullsource?QCC_MakeVectorConst(0,0,0):rhs, def, NULL, STFL_PRESERVEB));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_V], rhs, def, NULL, STFL_PRESERVEA|STFL_PRESERVEB));
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_V], nullsource?QCC_MakeVectorConst(0,0,0):rhs, def, NULL, STFL_PRESERVEA|STFL_PRESERVEB));
|
||||
i+=3;
|
||||
def.ofs += 3;
|
||||
rhs.ofs += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nullsource)
|
||||
rhs = QCC_MakeIntConst(0);
|
||||
|
||||
if (def.cast->type == ev_function)
|
||||
{
|
||||
rhs.cast = def.cast = type_function;
|
||||
|
@ -14721,9 +14903,8 @@ finalnotconst:
|
|||
QCC_FreeTemp(tmp);
|
||||
return ret;
|
||||
}
|
||||
//basedef can be null, meaning its initialising a temp
|
||||
//returns true where its a const/static initialiser. false if non-const/final initialiser
|
||||
pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags)
|
||||
|
||||
QCC_sref_t QCC_PR_ParseInitializerType_Internal(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags)
|
||||
{
|
||||
QCC_sref_t tmp;
|
||||
int i;
|
||||
|
@ -14751,6 +14932,7 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
}
|
||||
else
|
||||
{
|
||||
pbool isblock;
|
||||
QCC_type_t *type = def.cast;
|
||||
if (type->type == ev_function && pr_token_type == tt_punct)
|
||||
{
|
||||
|
@ -14912,6 +15094,13 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
{
|
||||
pr_scope = parentfunc;
|
||||
tmp = QCC_MakeIntConst(f - functions);
|
||||
|
||||
if (!basedef && def.sym->temp)
|
||||
{ //skip the store-to-temp
|
||||
QCC_FreeTemp(def);
|
||||
tmp.cast = def.cast;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type->type == ev_string && QCC_PR_CheckName("_"))
|
||||
|
@ -14936,15 +15125,17 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
}
|
||||
QCC_PR_Lex();
|
||||
QCC_PR_Expect(")");
|
||||
return ret;
|
||||
return ret?def:nullsref;
|
||||
}
|
||||
tmp = QCC_MakeTranslateStringConst(pr_immediate_string);
|
||||
QCC_PR_Lex();
|
||||
QCC_PR_Expect(")");
|
||||
}
|
||||
else if ((type->type == ev_struct && QCC_PR_CheckToken("{")) || (type->type == ev_union && ((type->num_parms == 1 && !type->params->paramname) || QCC_PR_CheckToken("{"))))
|
||||
else if ((isblock=(type->type == ev_struct || type->type == ev_union) && QCC_PR_CheckToken("{"))
|
||||
|| (type->type == ev_union && type->num_parms == 1 && !type->params->paramname))
|
||||
{
|
||||
//structs go recursive
|
||||
QCC_type_t *parenttype;
|
||||
unsigned int partnum;
|
||||
pbool isunion;
|
||||
gofs_t offset = def.ofs;
|
||||
|
@ -14954,7 +15145,7 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
memset(isinited, 0, sizeof(pbool)*type->size);
|
||||
|
||||
if (QCC_PR_PeekToken(".")) //won't be a float (.0 won't match)
|
||||
{
|
||||
{ //designated initialisers
|
||||
for(;;)
|
||||
{
|
||||
if (QCC_PR_CheckToken("."))
|
||||
|
@ -15003,39 +15194,43 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
ret &= QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, basedef, def, flags);
|
||||
if (isunion || !QCC_PR_CheckToken(","))
|
||||
{
|
||||
if (isunion && (type->num_parms == 1 && !type->params->paramname))
|
||||
if (!isblock)
|
||||
break;
|
||||
QCC_PR_Expect("}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; type; type = type->parentclass)
|
||||
|
||||
for (parenttype=type; parenttype; parenttype = parenttype->parentclass)
|
||||
{
|
||||
for (partnum = 0; partnum < (type)->num_parms; partnum++)
|
||||
for (partnum = 0; partnum < (parenttype)->num_parms; partnum++)
|
||||
{
|
||||
//copy into the def. should be from a const.
|
||||
def.cast = (type)->params[partnum].type;
|
||||
def.ofs = (type)->params[partnum].ofs;
|
||||
def.cast = (parenttype)->params[partnum].type;
|
||||
def.ofs = (parenttype)->params[partnum].ofs;
|
||||
if (isinited[def.ofs])
|
||||
continue;
|
||||
isinited[def.ofs] = true;
|
||||
def.ofs += offset;
|
||||
if ((type)->params[partnum].defltvalue.cast)
|
||||
tmp = (type)->params[partnum].defltvalue;
|
||||
if ((parenttype)->params[partnum].defltvalue.cast)
|
||||
tmp = (parenttype)->params[partnum].defltvalue;
|
||||
else
|
||||
tmp = QCC_MakeIntConst(0);
|
||||
QCC_ForceUnFreeDef(tmp.sym);
|
||||
QCC_PR_GenerateInitializerType(basedef, tmp, def, def.cast, flags);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
def.cast = type;
|
||||
def.ofs = offset;
|
||||
return ret?def:nullsref;
|
||||
}
|
||||
else if (type->type == ev_vector && QCC_PR_PeekToken("{"))
|
||||
{ //vectors can be treated as an array of 3 floats.
|
||||
def.cast = type_float;
|
||||
ret &= QCC_PR_ParseInitializerType(3, basedef, def, flags);
|
||||
return ret;
|
||||
def.cast = type;
|
||||
return ret?def:nullsref;
|
||||
}
|
||||
else if (type->type == ev_pointer && QCC_PR_CheckToken("{"))
|
||||
{
|
||||
|
@ -15086,7 +15281,22 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
|
|||
|
||||
ret = QCC_PR_GenerateInitializerType(basedef, tmp, def, type, flags);
|
||||
}
|
||||
return ret;
|
||||
return ret?def:nullsref;
|
||||
}
|
||||
QCC_sref_t QCC_PR_ParseInitializerTemp(QCC_type_t *type)
|
||||
{
|
||||
QCC_sref_t def = QCC_GetTemp(type);
|
||||
def = QCC_PR_ParseInitializerType_Internal(0, NULL, def, 0);
|
||||
if (def.cast != type)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "QCC_PR_ParseInitializerTemp changed type\n");
|
||||
return def;
|
||||
}
|
||||
//returns true where its a const/static initialiser. false if non-const/final initialiser
|
||||
pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags)
|
||||
{
|
||||
if (QCC_PR_ParseInitializerType_Internal(arraysize, basedef, def, flags).cast)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void QCC_PR_ParseInitializerDef(QCC_def_t *def, unsigned int flags)
|
||||
|
|
|
@ -5067,32 +5067,26 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
|
|||
}
|
||||
QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
|
||||
{
|
||||
QCC_type_t *ptype, *e;
|
||||
QCC_type_t *ptype;
|
||||
char name[128];
|
||||
if (pointsto->ptrto)
|
||||
return pointsto->ptrto;
|
||||
QC_snprintfz(name, sizeof(name), "%s*", pointsto->name);
|
||||
ptype = QCC_PR_NewType(name, ev_pointer, false);
|
||||
ptype = QCC_PR_NewType(strcpy(qccHunkAlloc(strlen(name)+1), name), ev_pointer, false);
|
||||
ptype->aux_type = pointsto;
|
||||
e = QCC_PR_FindType (ptype);
|
||||
if (e == ptype)
|
||||
{
|
||||
char name[128];
|
||||
QC_snprintfz(name, sizeof(name), "ptr to %s", pointsto->name);
|
||||
e->name = strcpy(qccHunkAlloc(strlen(name)+1), name);
|
||||
}
|
||||
pointsto->ptrto = e;
|
||||
return e;
|
||||
return pointsto->ptrto = QCC_PR_FindType (ptype);
|
||||
}
|
||||
QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
|
||||
{
|
||||
QCC_type_t *ptype;
|
||||
char name[128];
|
||||
QC_snprintfz(name, sizeof(name), "FIELD_TYPE(%s)", pointsto->name);
|
||||
ptype = QCC_PR_NewType(name, ev_field, false);
|
||||
if (pointsto->fldto)
|
||||
return pointsto->fldto;
|
||||
QC_snprintfz(name, sizeof(name), ".%s", pointsto->name);
|
||||
ptype = QCC_PR_NewType(strcpy(qccHunkAlloc(strlen(name)+1), name), ev_field, false);
|
||||
ptype->aux_type = pointsto;
|
||||
ptype->size = ptype->aux_type->size;
|
||||
return QCC_PR_FindType (ptype);
|
||||
return pointsto->fldto = QCC_PR_FindType (ptype);
|
||||
}
|
||||
QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s *args, int numargs)
|
||||
{
|
||||
|
|
|
@ -2482,8 +2482,8 @@ static void DebuggerStart(void)
|
|||
qcdebugger->setWorkingDirectory(enginebasedir);
|
||||
qcdebugger->setArguments(QStringList(cmdline));
|
||||
|
||||
QObject::connect(qcdebugger, static_cast<void(QProcess::*)(int)>(&QProcess::finished),
|
||||
[=](int exitcode)
|
||||
QObject::connect(qcdebugger, static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
|
||||
[=](int exitcode,QProcess::ExitStatus status)
|
||||
{
|
||||
// GUIprintf("Debuggee finished\n");
|
||||
// DebuggerStop(); //can't kill it here, there's still code running inside it
|
||||
|
|
|
@ -2162,7 +2162,7 @@ strofs = (strofs+3)&~3;
|
|||
}
|
||||
#ifdef _DEBUG
|
||||
if (((signed)a >= (signed)numpr_globals && statements[i].a.sym) || ((signed)b >= (signed)numpr_globals && statements[i].b.sym) || ((signed)c >= (signed)numpr_globals && statements[i].c.sym))
|
||||
externs->Printf("invalid offset on %s instruction\n", pr_opcodes[statements[i].op].opname);
|
||||
externs->Printf("invalid offset on %s instruction (from line %i)\n", pr_opcodes[statements[i].op].opname, statements[i].linenum);
|
||||
#endif
|
||||
//truncate to 16bit. should probably warn if the high bits are not 0x0000 or 0xffff
|
||||
statements16[i].a = (unsigned short)PRLittleShort((unsigned short)a);
|
||||
|
|
Loading…
Reference in a new issue