int conditional;
-extern int dotranslate;
-extern int dotranslate_count;
-
//standard qcc keywords
#define keyword_do 1
#define keyword_return 1
pbool keyword_break;
pbool keyword_case;
pbool keyword_class;
+pbool keyword_optional;
pbool keyword_const; //fixme
pbool keyword_continue;
pbool keyword_default;
pbool flag_msvcstyle; //MSVC style warnings, so msvc's ide works properly
pbool flag_assume_integer; //5 - is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
pbool flag_filetimes;
+pbool flag_typeexplicit; //no implicit type conversions, you must do the casts yourself.
pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp.
void *(*pHash_Add)(hashtable_t *table, const char *name, void *data, bucket_t *);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, pbool saved);
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
QCC_type_t *QCC_PR_FindType (QCC_type_t *type);
QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
-#define ASSOC_RIGHT_RESULT ASSOC_RIGHT
+//#define ASSOC_RIGHT_RESULT ASSOC_RIGHT
//========================================
//these are hexen2
{7, "*=", "MULSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
- {7, "*=", "MULSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector},
+ {7, "*=", "MULSTORE_VF", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector},
{7, "*=", "MULSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
- {7, "*=", "MULSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector},
+ {7, "*=", "MULSTOREP_VF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector},
{7, "/=", "DIVSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
{7, "/=", "DIVSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
{7, "<CALL8H>", "CALL8H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
{7, "=", "STORE_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer},
- {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_integer},
- {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_float},
+ {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_integer},
+ {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_float},
{7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
{7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
//var, offset return
{7, "<ARRAY>", "GET_POINTER", -1, ASSOC_LEFT, &type_float, &type_integer, &type_pointer},
- {7, "<ARRAY>", "ARRAY_OFS", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer},
+ {7, "<ARRAY>", "MUL4ADD_I", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer},
{7, "=", "LOADA_F", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float},
{7, "=", "LOADA_V", 6, ASSOC_LEFT, &type_vector, &type_integer, &type_vector},
{7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
-{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
+{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_integer, NULL, NULL},
-{7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void},
+{7, "<UNUSED>", "UNUSED", 6, ASSOC_RIGHT, &type_void, &type_void, &type_void},
{7, "<PUSH>", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer},
{7, "<POP>", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void},
{7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
{7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
- {7, "*=", "OP_MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "*=", "OP_MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "/=", "OP_DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "/=", "OP_DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "+=", "OP_ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "+=", "OP_ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "-=", "OP_SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
- {7, "-=", "OP_SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
-
- {7, "*=", "OP_MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "*=", "OP_MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "/=", "OP_DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "/=", "OP_DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "+=", "OP_ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "+=", "OP_ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "-=", "OP_SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
- {7, "-=", "OP_SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
+ {7, "*=", "MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
+ {7, "*=", "MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
+ {7, "/=", "DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
+ {7, "/=", "DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
+ {7, "+=", "ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
+ {7, "+=", "ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
+ {7, "-=", "SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
+ {7, "-=", "SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
+
+ {7, "*=", "MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
+ {7, "*=", "MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
+ {7, "/=", "DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
+ {7, "/=", "DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
+ {7, "+=", "ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
+ {7, "+=", "ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
+ {7, "-=", "SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
+ {7, "-=", "SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
+
+ {7, "*=", "MULSTORE_VI", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_integer, &type_vector},
+ {7, "*=", "MULSTOREP_VI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector},
+
+ {7, "=", "LOADA_STRUCT", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float},
+
+ {7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer},
{0, NULL}
};
#undef ASSOC_RIGHT_RESULT
#define TOP_PRIORITY 7
+#define FUNC_PRIORITY 1
#define UNARY_PRIORITY 1
#define NOT_PRIORITY 5
//conditional and/or
&pr_opcodes[OP_MUL_F],
&pr_opcodes[OP_MUL_V],
&pr_opcodes[OP_MUL_FV],
+ &pr_opcodes[OP_MUL_IV],
&pr_opcodes[OP_MUL_VF],
+ &pr_opcodes[OP_MUL_VI],
&pr_opcodes[OP_MUL_I],
+ &pr_opcodes[OP_MUL_FI],
+ &pr_opcodes[OP_MUL_IF],
&pr_opcodes[OP_DIV_F],
&pr_opcodes[OP_DIV_I],
+ &pr_opcodes[OP_DIV_FI],
+ &pr_opcodes[OP_DIV_IF],
&pr_opcodes[OP_DIV_VF],
&pr_opcodes[OP_BITAND_F],
NULL
}, { //6
+ &pr_opcodes[OP_STOREP_P],
+
&pr_opcodes[OP_STORE_F],
&pr_opcodes[OP_STORE_V],
&pr_opcodes[OP_STORE_S],
&pr_opcodes[OP_STOREP_I],
&pr_opcodes[OP_STOREP_IF],
&pr_opcodes[OP_STOREP_FI],
- &pr_opcodes[OP_STOREP_P],
&pr_opcodes[OP_DIVSTORE_F],
&pr_opcodes[OP_DIVSTORE_I],
&pr_opcodes[OP_DIVSTOREP_IF],
&pr_opcodes[OP_DIVSTOREP_FI],
&pr_opcodes[OP_MULSTORE_F],
- &pr_opcodes[OP_MULSTORE_V],
+ &pr_opcodes[OP_MULSTORE_VF],
+ &pr_opcodes[OP_MULSTORE_VI],
&pr_opcodes[OP_MULSTORE_I],
&pr_opcodes[OP_MULSTORE_IF],
&pr_opcodes[OP_MULSTORE_FI],
&pr_opcodes[OP_MULSTOREP_F],
- &pr_opcodes[OP_MULSTOREP_V],
+ &pr_opcodes[OP_MULSTOREP_VF],
+ &pr_opcodes[OP_MULSTOREP_VI],
&pr_opcodes[OP_MULSTOREP_I],
&pr_opcodes[OP_MULSTOREP_IF],
&pr_opcodes[OP_MULSTOREP_FI],
//stores into a pointer (generated from 'ent.field=XXX')
case OP_STOREP_I: //no worse than the other OP_STOREP_X functions
- case OP_STOREP_P:
//reads from an entity field
case OP_LOAD_I: //no worse than the other OP_LOAD_X functions.
case OP_LOAD_P:
return false; //DPFIXME: dp's bounds check may give false positives with expected uses.
case OP_MULSTORE_F:
- case OP_MULSTORE_V:
+ case OP_MULSTORE_VF:
case OP_MULSTOREP_F:
- case OP_MULSTOREP_V: // e.v *= f
+ case OP_MULSTOREP_VF: // e.v *= f
case OP_DIVSTORE_F:
case OP_DIVSTOREP_F:
case OP_STORE_IF:
QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement);
static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
{
+ /*no conversion needed*/
+ if (var->type->type == wanted)
+ return 0;
if (var->type->type == ev_integer && wanted == ev_function)
return 0;
+ if (var->type->type == ev_integer && wanted == ev_pointer)
+ return 0;
+ /*stuff needs converting*/
if (var->type->type == ev_pointer && var->type->aux_type)
{
if (var->type->aux_type->type == ev_float && wanted == ev_integer)
return OP_CONV_ITOF;
}
+ /*impossible*/
return -1;
}
-QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted)
+QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal)
{
+ extern char *basictypenames[];
int o;
if (pr_classtype && var->type->type == ev_field && wanted != ev_field)
if (pr_classtype)
{ //load self.var into a temp
QCC_def_t *self;
- self = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+ self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
switch(wanted)
{
case ev_float:
o = QCC_ShouldConvert(var, wanted);
- if (o <= 0) //no conversion
+ if (o == 0) //type already matches
return var;
-
+ if (flag_typeexplicit)
+ QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
+ if (o < 0)
+ {
+ if (fatal)
+ QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
+ else
+ return var;
+ }
return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value
}
-QCC_def_t *QCC_MakeStringDef(char *value);
-QCC_def_t *QCC_MakeFloatDef(float value);
-QCC_def_t *QCC_MakeIntDef(int value);
-QCC_def_t *QCC_MakeVectorDef(float a, float b, float c);
+QCC_def_t *QCC_MakeTranslateStringConst(char *value);
+QCC_def_t *QCC_MakeStringConst(char *value);
+QCC_def_t *QCC_MakeFloatConst(float value);
+QCC_def_t *QCC_MakeIntConst(int value);
+QCC_def_t *QCC_MakeVectorConst(float a, float b, float c);
typedef struct freeoffset_s {
struct freeoffset_s *next;
while(t)
{
if (t->used && !pr_error_count) //don't print this after an error jump out.
- {
- QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used in %s", pr_scope->name);
- t->used = false;
- }
+ QCC_PR_ParseWarning(WARN_DEBUGGING, "Internal: temp(ofs %i) was not released in %s. This implies miscompilation.", t->ofs, pr_scope->name);
+ t->used = false;
t = t->next;
}
}
if (d->temp && d->temp->used)
d->temp->scope = pr_scope;
}
+static void QCC_ForceLockTempForOffset(int ofs)
+{
+ temp_t *t;
+ for (t = functemps; t; t = t->next)
+ if(t->ofs == ofs /* && t->used */)
+ t->scope = pr_scope;
+}
static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement)
{
{
if (var->ofs >= paramstart && var->ofs < paramend)
continue;
- fprintf(f, "local %s %s; /* at %d */\n", TypeName(var->type), var->name, var->ofs);
+ if (var->arraysize)
+ fprintf(f, "local %s %s[%i];\n", TypeName(var->type), var->name, var->arraysize);
+ else
+ fprintf(f, "local %s %s;\n", TypeName(var->type), var->name);
}
for (t = functemps, i = 0; t; t = t->next, i++)
{
if (t->lastfunc == pr_scope)
{
- fprintf(f, "local %s temp_%i; /* at %d */\n", (t->size == 1)?"float":"vector", i, t->ofs);
+ fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i);
}
}
}
if (ofs >= t->ofs && ofs < t->ofs + t->size)
{
if (size < t->size)
- sprintf(message, "temp_%i_%c", i, 'x' + (ofs-t->ofs)%3);
+ sprintf(message, "temp_%i_%c", t->ofs, 'x' + (ofs-t->ofs)%3);
else
- sprintf(message, "temp_%i", i);
+ sprintf(message, "temp_%i", t->ofs);
return message;
}
}
}
#endif
-QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
+QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force);
+
+QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
{
QCC_dstatement_t *statement;
QCC_def_t *var_c=NULL, *temp=NULL;
if (outstatement == (QCC_dstatement_t **)0xffffffff)
outstatement = NULL;
- else if (op->priority != -1)
+ else if (op->priority != -1 && op->priority != CONDITION_PRIORITY)
{
if (op->associative!=ASSOC_LEFT)
{
- if (op->type_a == &type_pointer)
- var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
- else
- var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type);
+ if (op->type_a != &type_pointer)
+ var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type, false);
}
else
{
if (var_a)
- var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
+ var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type, false);
if (var_b)
- var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
-// if (op->type_a == &def_pointer)
-// var_a = QCC_SupplyConversion(var_a, (*op->type_b)->type);
-// else
-// var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
-// }
-// //can't convert the left componant of an assignment operation
-// if (var_b && var_b->type && var_b->type != op->type_b->type)
-// var_b = QCC_SupplyConversion(var_b, op->type_b->type->type);
+ var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type, false);
}
}
//both are constants
switch (op - pr_opcodes) //improve some of the maths.
{
+ case OP_LOADA_F:
+ case OP_LOADA_V:
+ case OP_LOADA_S:
+ case OP_LOADA_ENT:
+ case OP_LOADA_FLD:
+ case OP_LOADA_FNC:
+ case OP_LOADA_I:
+ {
+ QCC_def_t *nd;
+ nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (nd, 0, sizeof(QCC_def_t));
+ nd->type = var_a->type;
+ nd->ofs = var_a->ofs + G_INT(var_b->ofs);
+ nd->temp = var_a->temp;
+ nd->constant = true;
+ nd->name = var_a->name;
+ return nd;
+ }
+ break;
case OP_BITOR_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
+ return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
case OP_BITAND_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
+ return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
case OP_MUL_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
+ return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
case OP_DIV_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
+ return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
case OP_ADD_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
+ return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
case OP_SUB_F:
optres_constantarithmatic++;
- return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
+ return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
case OP_BITOR_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) | G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) | G_INT(var_b->ofs));
case OP_BITAND_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) & G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) & G_INT(var_b->ofs));
case OP_MUL_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) * G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) * G_INT(var_b->ofs));
case OP_DIV_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) / G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) / G_INT(var_b->ofs));
case OP_ADD_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) + G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) + G_INT(var_b->ofs));
case OP_SUB_I:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) - G_INT(var_b->ofs));
case OP_AND_F:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs));
case OP_OR_F:
optres_constantarithmatic++;
- return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs));
+ return QCC_MakeIntConst(G_INT(var_a->ofs) || G_INT(var_b->ofs));
case OP_MUL_V: //mul_f is actually a dot-product
optres_constantarithmatic++;
- return QCC_MakeFloatDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
+ return QCC_MakeFloatConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1) +
G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
case OP_MUL_FV:
optres_constantarithmatic++;
- return QCC_MakeVectorDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
+ return QCC_MakeVectorConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1),
G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
case OP_MUL_VF:
optres_constantarithmatic++;
- return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
+ return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
G_FLOAT(var_a->ofs+1) * G_FLOAT(var_b->ofs),
G_FLOAT(var_a->ofs+2) * G_FLOAT(var_b->ofs));
case OP_ADD_V:
optres_constantarithmatic++;
- return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
+ return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
G_FLOAT(var_a->ofs+1) + G_FLOAT(var_b->ofs+1),
G_FLOAT(var_a->ofs+2) + G_FLOAT(var_b->ofs+2));
case OP_SUB_V:
optres_constantarithmatic++;
- return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
+ return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
G_FLOAT(var_a->ofs+1) - G_FLOAT(var_b->ofs+1),
G_FLOAT(var_a->ofs+2) - G_FLOAT(var_b->ofs+2));
}
//a is const, b is not
switch (op - pr_opcodes)
{
+ case OP_CONV_FTOI:
+ optres_constantarithmatic++;
+ return QCC_MakeIntConst(G_FLOAT(var_a->ofs));
+ case OP_CONV_ITOF:
+ optres_constantarithmatic++;
+ return QCC_MakeFloatConst(G_INT(var_a->ofs));
case OP_BITOR_F:
case OP_OR_F:
case OP_ADD_F:
//b is const, a is not
switch (op - pr_opcodes)
{
+ case OP_LOADA_F:
+ case OP_LOADA_V:
+ case OP_LOADA_S:
+ case OP_LOADA_ENT:
+ case OP_LOADA_FLD:
+ case OP_LOADA_FNC:
+ case OP_LOADA_I:
+ {
+ QCC_def_t *nd;
+ nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (nd, 0, sizeof(QCC_def_t));
+ nd->type = var_a->type;
+ nd->ofs = var_a->ofs + G_INT(var_b->ofs);
+ nd->temp = var_a->temp;
+ nd->constant = false;
+ nd->name = var_a->name;
+ return nd;
+ }
+ break;
case OP_BITOR_F:
case OP_OR_F:
case OP_SUB_F:
return var_a;
}
case OP_AND_I:
- if (G_INT(var_b->ofs) != 0)
+ if (G_INT(var_b->ofs) == 0)
{
optres_constantarithmatic++;
QCC_UnFreeTemp(var_a);
switch (op - pr_opcodes)
{
+ case OP_LOADA_F:
+ case OP_LOADA_V:
+ case OP_LOADA_S:
+ case OP_LOADA_ENT:
+ case OP_LOADA_FLD:
+ case OP_LOADA_FNC:
+ case OP_LOADA_I:
+ break;
case OP_AND_F:
if (var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
{
switch(op - pr_opcodes)
{
+ case OP_LOADA_STRUCT:
+ /*emit this anyway. if it reaches runtime then you messed up.
+ this is valid only if you do &foo[0]*/
+ break;
+
+
case OP_IF_S:
- var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
+ var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
numstatements--;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
statement = &statements[numstatements];
break;
case OP_IFNOT_S:
- var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
+ var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
numstatements--;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
statement = &statements[numstatements];
break;
case OP_IF_F:
- var_c = QCC_MakeFloatDef(0);
+ var_c = QCC_MakeFloatConst(0);
numstatements--;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
statement = &statements[numstatements];
break;
case OP_IFNOT_F:
- var_c = QCC_MakeFloatDef(0);
+ var_c = QCC_MakeFloatConst(0);
numstatements--;
var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
statement = &statements[numstatements];
var_a = var_c;
var_c = var_a;
break;
+ case OP_ADDSTORE_I:
+ op = &pr_opcodes[OP_ADD_I];
+ var_c = var_b;
+ var_b = var_a;
+ var_a = var_c;
+ var_c = var_a;
+ break;
case OP_ADDSTORE_FI:
op = &pr_opcodes[OP_ADD_FI];
var_c = var_b;
var_c = var_a;
break;
- case OP_MULSTORE_V:
+ case OP_MULSTORE_VF:
op = &pr_opcodes[OP_MUL_VF];
var_c = var_b;
var_b = var_a;
var_a = var_c;
var_c = var_a;
break;
+ case OP_MULSTORE_VI:
+ op = &pr_opcodes[OP_MUL_VI];
+ var_c = var_b;
+ var_b = var_a;
+ var_a = var_c;
+ var_c = var_a;
+ break;
case OP_BITSET_I:
op = &pr_opcodes[OP_BITOR_I];
var_c = var_a;
break;
+ case OP_STOREP_P:
+ op = &pr_opcodes[OP_STOREP_I];
+ break;
+
case OP_BITCLR:
//b = var, a = bit field.
case OP_DIVSTOREP_FI:
case OP_DIVSTOREP_IF:
+ case OP_MULSTOREP_VF:
+ case OP_MULSTOREP_VI:
+ case OP_SUBSTOREP_V:
+ case OP_ADDSTOREP_V:
case OP_SUBSTOREP_F:
+ case OP_SUBSTOREP_I:
+ case OP_ADDSTOREP_I:
case OP_ADDSTOREP_F:
case OP_MULSTOREP_F:
case OP_DIVSTOREP_F:
{
int st;
int need_lock = false;
- for (st = numstatements-2; st>=0; st--)
+ if (var_b->temp)
{
- if (statements[st].op == OP_ADDRESS)
- if (statements[st].c == var_b->ofs)
- break;
+ for (st = numstatements-2; st>=0; st--)
+ {
+ if (statements[st].op == OP_ADDRESS)
+ if (statements[st].c == var_b->ofs)
+ break;
- if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
- need_lock = true;
+ if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
+ need_lock = true;
- if (statements[st].c == var_b->ofs)
- QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
+ if (statements[st].c == var_b->ofs)
+ {
+ st = -1;
+ break;
+ }
+ }
}
- if (st < 0)
- QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement");
+ else
+ st = -1;
+
var_c = QCC_GetTemp(*op->type_c);
- if (need_lock)
- QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
+ if (st < 0)
+ {
+ /*generate new OP_LOADP instruction*/
+ statement->op = ((*op->type_c)->type==ev_vector)?OP_LOADP_V:OP_LOADP_F;
+ statement->a = var_b->ofs;
+ statement->b = var_c->ofs;
+ statement->c = 0;
+ }
+ else
+ {
+ /*it came from an OP_ADDRESS - st says the instruction*/
+ if (need_lock)
+ {
+ QCC_ForceLockTempForOffset(statements[st].a);
+ QCC_ForceLockTempForOffset(statements[st].b);
+ QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
+ }
- statement_linenums[statement-statements] = statement_linenums[st];
- statement->op = OP_ADDRESS;
- statement->a = statements[st].a;
- statement->b = statements[st].b;
- statement->c = statements[st].c;
+ /*generate new OP_ADDRESS instruction - FIXME: the arguments may have changed since the original instruction*/
+ statement_linenums[statement-statements] = statement_linenums[st];
+ statement->op = OP_ADDRESS;
+ statement->a = statements[st].a;
+ statement->b = statements[st].b;
+ statement->c = statements[st].c;
- statement_linenums[st] = pr_source_line;
- statements[st].op = OP_LOAD_F;
- statements[st].a = statements[st].a;
- statements[st].b = statements[st].b;
- statements[st].c = var_c->ofs;
+ /*convert old one to an OP_LOAD*/
+ statement_linenums[st] = pr_source_line;
+ statements[st].op = ((*op->type_c)->type==ev_vector)?OP_LOAD_V:OP_LOAD_F;
+ statements[st].a = statements[st].a;
+ statements[st].b = statements[st].b;
+ statements[st].c = var_c->ofs;
+ }
}
statement = &statements[numstatements];
statement_linenums[statement-statements] = pr_source_line;
switch(op - pr_opcodes)
{
+ case OP_SUBSTOREP_V:
+ statement->op = OP_SUB_V;
+ break;
+ case OP_ADDSTOREP_V:
+ statement->op = OP_ADD_V;
+ break;
+ case OP_MULSTOREP_VF:
+ statement->op = OP_MUL_VF;
+ break;
+ case OP_MULSTOREP_VI:
+ statement->op = OP_MUL_VI;
+ break;
case OP_SUBSTOREP_F:
statement->op = OP_SUB_F;
break;
+ case OP_SUBSTOREP_I:
+ statement->op = OP_SUB_I;
+ break;
case OP_SUBSTOREP_IF:
statement->op = OP_SUB_IF;
break;
case OP_ADDSTOREP_F:
statement->op = OP_ADD_F;
break;
+ case OP_ADDSTOREP_I:
+ statement->op = OP_ADD_I;
+ break;
case OP_MULSTOREP_F:
statement->op = OP_MUL_F;
break;
var_a = var_c; //this is the value.
}
- op = &pr_opcodes[OP_STOREP_F];
+ op = &pr_opcodes[((*op->type_c)->type==ev_vector)?OP_STOREP_V:OP_STOREP_F];
QCC_FreeTemp(var_c);
var_c = NULL;
QCC_FreeTemp(var_b);
numstatements++;
break;
- case OP_MULSTOREP_V:
- case OP_SUBSTOREP_V:
- case OP_ADDSTOREP_V:
-// QCC_PR_ParseWarning(0, "XSTOREP_V emulation is still experimental");
- QCC_UnFreeTemp(var_a);
- QCC_UnFreeTemp(var_b);
- //don't chain these... this expansion is not the same.
- {
- int st;
- int need_lock = false;
- for (st = numstatements-2; st>=0; st--)
- {
- if (statements[st].op == OP_ADDRESS)
- if (statements[st].c == var_b->ofs)
- break;
-
- if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
- need_lock = true;
-
- if (statements[st].c == var_b->ofs)
- QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
- }
- if (st < 0)
- QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_V couldn't find pointer generation");
- var_c = QCC_GetTemp(*op->type_c);
- if (need_lock)
- QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
-
- statement_linenums[statement-statements] = statement_linenums[st];
- statement->op = OP_ADDRESS;
- statement->a = statements[st].a;
- statement->b = statements[st].b;
- statement->c = statements[st].c;
-
- statement_linenums[st] = pr_source_line;
- statements[st].op = OP_LOAD_V;
- statements[st].a = statements[st].a;
- statements[st].b = statements[st].b;
- statements[st].c = var_c->ofs;
- }
-
- statement = &statements[numstatements];
- numstatements++;
-
- statement_linenums[statement-statements] = pr_source_line;
- switch(op - pr_opcodes)
- {
- case OP_SUBSTOREP_V:
- statement->op = OP_SUB_V;
- break;
- case OP_ADDSTOREP_V:
- statement->op = OP_ADD_V;
- break;
- case OP_MULSTOREP_V:
- statement->op = OP_MUL_VF;
- break;
- default: //no way will this be hit...
- QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes);
- }
- statement->a = var_a ? var_a->ofs : 0;
- statement->b = var_c ? var_c->ofs : 0;
- QCC_FreeTemp(var_c);
- var_c = QCC_GetTemp(*op->type_c);
- statement->c = var_c ? var_c->ofs : 0;
-
- var_b = var_b; //this is the ptr.
- QCC_FreeTemp(var_a);
- var_a = var_c; //this is the value.
- op = &pr_opcodes[OP_STOREP_V];
-
-
-
-
- QCC_FreeTemp(var_c);
- var_c = NULL;
- QCC_FreeTemp(var_b);
-
- statement = &statements[numstatements];
- numstatements++;
- break;
default:
QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname);
break;
if (pr_immediate_type == type_float)
{
- cn = QCC_MakeFloatDef(pr_immediate._float);
+ cn = QCC_MakeFloatConst(pr_immediate._float);
QCC_PR_Lex ();
return cn;
}
if (pr_immediate_type == type_integer)
{
- cn = QCC_MakeIntDef(pr_immediate._int);
+ cn = QCC_MakeIntConst(pr_immediate._int);
QCC_PR_Lex ();
return cn;
}
if (pr_immediate_type == type_string)
{
- cn = QCC_MakeStringDef(pr_immediate_string);
- QCC_PR_Lex ();
+ char tmp[8192];
+ strcpy(tmp, pr_immediate_string);
+
+ for(;;)
+ {
+ QCC_PR_Lex ();
+ if (pr_token_type == tt_immediate && pr_token_type == tt_immediate)
+ strcat(tmp, pr_immediate_string);
+ else
+ break;
+ }
+
+ cn = QCC_MakeStringConst(tmp);
return cn;
}
//FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self'
//thiscall. copy the right ent into 'self' (if it's not the same offset)
- d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+ d = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
if (statements[laststatement-1].a != d->ofs)
{
oself = QCC_GetTemp(type_entity);
//first two args are passed in the call opcode, so don't need to be copied
arglist[i]->references++;
d->references++;
- QCC_FreeTemp(arglist[i]);
+ /*don't free these temps yet, free them after the return check*/
continue;
}
- if (arglist[i]->type->size>1 || !opt_nonvec_parms)
+ if (arglist[i]->type->size == 3 || !opt_nonvec_parms)
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
else
{
//if the return value was in use, save it off now, so that it doesn't get clobbered
if (def_ret.temp->used)
- {
oldret = QCC_GetTemp(def_ret.type);
+ else
+ oldret = NULL;
+
+ /*can free temps used for arguments now*/
+ if (callconvention == OP_CALL1H)
+ {
+ for (i = 0; i < argcount && i < 2; i++)
+ QCC_FreeTemp(arglist[i]);
+ }
+
+ if (oldret && !def_ret.temp->used)
+ {
+ QCC_FreeTemp(oldret);
+ oldret = NULL;
+ }
+ else if (def_ret.temp->used)
+ {
if (def_ret.type->size == 3)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, (void*)0xffffffff));
else
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, (void*)0xffffffff));
QCC_UnFreeTemp(oldret);
QCC_UnFreeTemp(&def_ret);
QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
if (oself)
QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false);
- for(; argcount; argcount--)
- {
- QCC_FreeTemp(arglist[argcount-1]);
- }
-
if (oldret)
{
- // Make sure our def_ret backup temp wasn't freed above
- QCC_UnFreeTemp(oldret); //this bug fix was brought to you by Blub, the character \ and the number 0.
-
+ if (oldret->temp && !oldret->temp->used)
+ QCC_PR_ParseWarning(0, "Ret was freed\n");
//if we preserved the ofs_ret global, restore it here
if (t->type == ev_variant)
{
d = QCC_GetTemp(type_variant);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
}
else
{
d = QCC_GetTemp(t->aux_type);
if (t->aux_type->size == 3)
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, (void*)0xffffffff));
else
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
}
if (def_ret.type->size == 3)
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, (void*)0xffffffff));
else
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, (void*)0xffffffff));
QCC_FreeTemp(oldret);
QCC_UnFreeTemp(&def_ret);
QCC_UnFreeTemp(d);
if (!t->num_parms&&t->type != ev_variant) //intrinsics. These base functions have variable arguments. I would check for (...) args too, but that might be used for extended builtin functionality. (this code wouldn't compile otherwise)
{
+ if (!strcmp(func->name, "sizeof"))
+ {
+ QCC_type_t *t;
+ if (!func->initialized)
+ func->initialized = 3;
+ func->references++;
+ t = QCC_PR_ParseType(false, false);
+ QCC_PR_Expect(")");
+ return QCC_MakeIntConst(t->size * 4);
+ }
+ if (!strcmp(func->name, "_"))
+ {
+ if (!func->initialized)
+ func->initialized = 3;
+ func->references++;
+ if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
+ {
+ d = QCC_MakeTranslateStringConst(pr_immediate_string);
+ QCC_PR_Lex();
+ }
+ else
+ QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "_() intrinsic accepts only a string immediate", 1);
+ QCC_PR_Expect(")");
+ return d;
+ }
if (!strcmp(func->name, "random"))
{
old = NULL;
+ if (!func->initialized)
+ func->initialized = 3;
func->references++;
if (!QCC_PR_CheckToken(")"))
{
d = NULL;
}
+ out = &def_ret;
if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0]))
{
- if(def_ret.temp->used)
+ if(qcc_targetformat != QCF_HEXEN2)
out = QCC_GetTemp(type_float);
+ else if (out->temp->used)
+ {
+ old = QCC_GetTemp(out->type);
+ if (def_ret.type->size == 3)
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
+ else
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
+ QCC_UnFreeTemp(old);
+ QCC_UnFreeTemp(out);
+ QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
+ }
else
- out = &def_ret;
+ old = NULL;
if (e)
{
}
else
{
- if (def_ret.temp->used)
+ if (out->temp->used)
{
- old = QCC_GetTemp(def_ret.type);
+ old = QCC_GetTemp(out->type);
if (def_ret.type->size == 3)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
else
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
QCC_UnFreeTemp(old);
- QCC_UnFreeTemp(&def_ret);
+ QCC_UnFreeTemp(out);
QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
}
else
return d;
}
- if (def_ret.temp->used)
- QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
- def_ret.temp->used = true;
- def_ret.type = type_float;
- return &def_ret;
+ if (out == &def_ret)
+ {
+ if (out->temp->used)
+ QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
+ out->temp->used = true;
+ out->type = type_float;
+ }
+ return out;
}
if (!strcmp(func->name, "randomv"))
{
out = NULL;
+ if (!func->initialized)
+ func->initialized = 3;
func->references++;
if (!QCC_PR_CheckToken(")"))
{
{
char genfunc[2048];
sprintf(genfunc, "Class*%s", rettype->name);
- func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 1, false);
+ func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, false);
func->references++;
}
QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
{
//t = (a/%1) / (nextent(world)/%1)
//a/%1 does a (int)entity to float conversion type thing
- func->initialized = 1;
+ if (!func->initialized)
+ func->initialized = 3;
+ func->references++;
e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
QCC_PR_Expect(")");
- e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
+ e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
d = QCC_PR_GetDef(NULL, "nextent", NULL, false, 0, false);
if (!d)
QCC_PR_ParseError(0, "the nextent builtin is not defined");
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff));
d = QCC_PR_Statement(&pr_opcodes[OP_CALL0], d, NULL, NULL);
- d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
+ d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, d, (QCC_dstatement_t **)0xffffffff);
return e;
}
- else if (!strcmp(func->name, "_") && !QCC_PR_CheckToken(")"))
- {
- // return string as is, but set the dotranslate flag
- ++dotranslate;
- e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
- --dotranslate;
- QCC_PR_Expect(")");
- return e;
- }
} //so it's not an intrinsic.
if (opt_precache_file) //should we strip out all precache_file calls?
{
if (!strncmp(func->name,"precache_file", 13))
{
- if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
+ if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string && pr_scope && !strcmp(pr_scope->name, "main"))
{
optres_precache_file += strlen(pr_immediate_string);
QCC_PR_Lex();
QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS);
else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS);
- if (!extraparms && arg >= t->num_parms)
+ if (!extraparms && arg >= t->num_parms && !p)
{
QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
e = &def_parms[arg];
e->ofs = OFS_PARM0+0;
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
e->ofs = OFS_PARM0+1;
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
e->ofs = OFS_PARM0+2;
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
e->ofs = OFS_PARM0;
+ e->type = type_vector;
QCC_PR_Lex();
}
if (pr_classtype && e->type->type == ev_field && p->type != ev_field)
{ //convert.
- oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+ oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
switch(e->type->aux_type->type)
{
case ev_string:
e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant?
e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
- else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
+ else if ((p->type == ev_function && p->type == ev_string) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
{ //you're allowed to use int 0 to pass a null function pointer
//this is basically because __NULL__ is defined as ~0 (int 0)
}
- else if (p->type != ev_variant) //can cast to variant whatever happens
+ else if (p->type != ev_variant && e->type->type != ev_variant) //can cast to variant whatever happens
{
if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
{
int constchecks;
int varchecks;
int typechecks;
-QCC_def_t *QCC_MakeIntDef(int value)
+QCC_def_t *QCC_MakeIntConst(int value)
{
QCC_def_t *cn;
cn->constant = true;
cn->initialized = 1;
cn->scope = NULL; // always share immediates
- cn->arraysize = 1;
+ cn->arraysize = 0;
-// copy the immediate to the global area
- cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
+ if (!value)
+ G_INT(cn->ofs) = 0;
+ else
+ {
+ // copy the immediate to the global area
+ cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
- G_INT(cn->ofs) = value;
+ G_INT(cn->ofs) = value;
+ }
return cn;
}
-QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
+QCC_def_t *QCC_MakeVectorConst(float a, float b, float c)
{
QCC_def_t *cn;
cn->constant = true;
cn->initialized = 1;
cn->scope = NULL; // always share immediates
- cn->arraysize = 1;
+ cn->arraysize = 0;
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]);
return cn;
}
-hashtable_t floatconstdefstable;
-QCC_def_t *QCC_MakeFloatDef(float value)
+extern hashtable_t floatconstdefstable;
+QCC_def_t *QCC_MakeFloatConst(float value)
{
QCC_def_t *cn;
cn->constant = true;
cn->initialized = 1;
cn->scope = NULL; // always share immediates
- cn->arraysize = 1;
+ cn->arraysize = 0;
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
return cn;
}
-extern hashtable_t stringconstdefstable;
-extern hashtable_t stringconstdefstable_dotranslate;
-QCC_def_t *QCC_MakeStringDef(char *value)
+extern hashtable_t stringconstdefstable, stringconstdefstable_trans;
+int dotranslate_count;
+static QCC_def_t *QCC_MakeStringConstInternal(char *value, pbool translate)
{
QCC_def_t *cn;
int string;
- hashtable_t *tbl = dotranslate ? &stringconstdefstable_dotranslate : &stringconstdefstable;
- char buf[64];
- cn = pHash_Get(tbl, value);
+ cn = pHash_Get(translate?&stringconstdefstable_trans:&stringconstdefstable, value);
if (cn)
return cn;
// allocate a new one
- cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ if(translate)
+ {
+ char buf[64];
+ sprintf(buf, "dotranslate_%i", ++dotranslate_count);
+ cn = (void *)qccHunkAlloc (sizeof(QCC_def_t) + strlen(buf)+1);
+ cn->name = (char*)(cn+1);
+ strcpy(cn->name, buf);
+ }
+ else
+ {
+ cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ cn->name = "IMMEDIATE";
+ }
cn->next = NULL;
pr.def_tail->next = cn;
pr.def_tail = cn;
cn->type = type_string;
- if(dotranslate > 0)
- {
- sprintf(buf, "dotranslate_%d", ++dotranslate_count);
- cn->name = strdup(buf);
- }
- else
- cn->name = "IMMEDIATE";
cn->constant = true;
cn->initialized = 1;
cn->scope = NULL; // always share immediates
- cn->arraysize = 1;
+ cn->arraysize = 0;
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
string = QCC_CopyString (value);
- pHash_Add(tbl, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
+ pHash_Add(translate?&stringconstdefstable_trans:&stringconstdefstable, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
G_INT(cn->ofs) = string;
-
return cn;
}
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
+QCC_def_t *QCC_MakeStringConst(char *value)
+{
+ return QCC_MakeStringConstInternal(value, false);
+}
+QCC_def_t *QCC_MakeTranslateStringConst(char *value)
+{
+ return QCC_MakeStringConstInternal(value, true);
+}
+
QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type)
{
QCC_type_t *newtype;
- newtype = QCC_PR_NewType("POINTER TYPE", ev_pointer);
+ newtype = QCC_PR_NewType("ptr", ev_pointer, false);
newtype->aux_type = type;
return newtype;
}
f = QCC_MemberInParentClass(mt->name, clas->parentclass);
if (f)
{
- if (m->arraysize>1)
+ if (m->arraysize)
QCC_Error(ERR_INTERNAL, "FTEQCC does not support overloaded arrays of members");
a=0;
for (o = 0; o < m->type->size; o++)
continue;
}
- for (a = 0; a < m->arraysize; a++)
+ for (a = 0; a < (m->arraysize?m->arraysize:1); a++)
{
+ /*if it was already set, don't go recursive and generate 500 fields for a one-member class that was intheritted from 500 times*/
+ if (((int *)qcc_pr_globals)[o+a*mt->size+m->ofs])
+ continue;
+
//we need the type in here so saved games can still work without saving ints as floats. (would be evil)
- ft = QCC_PR_NewType(basictypenames[mt->type], ev_field);
- ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type);
+ ft = QCC_PR_NewType(basictypenames[mt->type], ev_field, false);
+ ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type, false);
ft->aux_type->aux_type = type_void;
ft->size = ft->aux_type->size;
ft = QCC_PR_FindType(ft);
sprintf(membername, "__f_%s_%i", ft->name, ++basictypefield[mt->type]);
- f = QCC_PR_GetDef(ft, membername, NULL, true, 1, true);
+ f = QCC_PR_GetDef(ft, membername, NULL, true, 0, true);
for (o = 0; o < m->type->size; o++)
((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
if (type->type == ev_function) //FIXME: inheritance will not install all the member functions.
{
sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, type->name);
- member = QCC_PR_GetDef(NULL, membername, NULL, false, 1, false);
+ member = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
if (!member)
{
QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername);
}
point = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], ed, member, NULL);
sprintf(membername, "%s::%s", clas->name, type->name);
- virt = QCC_PR_GetDef(type, membername, NULL, false, 1, false);
+ virt = QCC_PR_GetDef(type, membername, NULL, false, 0, false);
QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL);
}
}
if (!basetype)
QCC_PR_ParseError(ERR_INTERNAL, "Type %s was not defined...", tname);
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
pr_scope = NULL;
memset(basictypefield, 0, sizeof(basictypefield));
G_FUNCTION(scope->ofs) = df - functions;
//locals here...
- ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 1, false);
+ ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 0, false);
virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false);
if (!virt)
if (constructor)
{ //self = ent;
self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
- oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 1, false);
+ oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 0, false);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL));
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL)); //return to our old self. boom boom.
QCC_PR_SimpleStatement(OP_CALL0, constructor->ofs, 0, 0, false);
locals_end = numpr_globals + basetype->size;
df->locals = locals_end - df->parm_start;
}
-/*
-============
-PR_ParseValue
-Returns the global ofs for the current token
-============
-*/
-QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
+QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign)
{
- QCC_def_t *ao=NULL; //arrayoffset
- QCC_def_t *d, *nd, *od;
- char *name;
+ QCC_type_t *t;
+ QCC_def_t *idx;
+ QCC_def_t *tmp;
QCC_dstatement_t *st;
- int i;
- static QCC_def_t intrinsic = {
- NULL, // QCC_type_t *type;
- NULL, // char *name;
- NULL, // struct QCC_def_s *next;
- NULL, // struct QCC_def_s *nextlocal; //provides a chain of local variables for the opt_locals_marshalling optimisation.
- 0, // gofs_t ofs;
- NULL, // struct QCC_def_s *scope; // function the var was defined in, or NULL
- 1, // int initialized; // 1 when a declaration included "= immediate"
- 1, // int constant; // 1 says we can use the value over and over again
- 1, // int references;
- 0, // int timescalled; //part of the opt_stripfunctions optimisation.
- 0, // int s_file;
- 0, // int s_line;
- 0, // int arraysize;
- 0, // pbool shared;
- 0, // pbool saved;
- 0, // pbool isstatic;
- NULL // temp_t *temp;
- };
+ pbool allowarray;
- char membername[2048];
+ t = d->type;
+ idx = NULL;
+ while(1)
+ {
+ allowarray = false;
+ if (idx)
+ allowarray = t->arraysize>0;
+ else if (!idx)
+ {
+ allowarray = d->arraysize ||
+ (d->type->type == ev_pointer) ||
+ (d->type->type == ev_string) ||
+ (d->type->type == ev_vector);
+ }
-// if the token is an immediate, allocate a constant for it
- if (pr_token_type == tt_immediate)
- return QCC_PR_ParseImmediate ();
+ if (allowarray && QCC_PR_CheckToken("["))
+ {
+ tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
+ QCC_PR_Expect("]");
- if (QCC_PR_CheckToken("[")) //reacc support
- { //looks like a funky vector. :)
- vec3_t v;
- pr_immediate_type = type_vector;
- v[0] = pr_immediate._float;
- QCC_PR_Lex();
- v[1] = pr_immediate._float;
- QCC_PR_Lex();
- v[2] = pr_immediate._float;
- pr_immediate.vector[0] = v[0];
- pr_immediate.vector[1] = v[1];
- pr_immediate.vector[2] = v[2];
- pr_immediate_type = type_vector;
- d = QCC_PR_ParseImmediate();
- QCC_PR_Expect("]");
- return d;
- }
- name = QCC_PR_ParseName ();
-
- if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar'
- { //try getting a member.
- QCC_type_t *type;
- type = assumeclass;
- d = NULL;
- while(type != type_entity && type)
- {
- sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
- od = d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
- if (d)
- break;
-
- type = type->parentclass;
- }
- if (!d)
- od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
- }
- else
-
-// look through the defs
- od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
+ /*if its a pointer that got dereferenced, follow the type*/
+ if (!idx && t->type == ev_pointer && !d->arraysize)
+ t = t->aux_type;
- if (!d)
- {
- if ( (!strcmp(name, "random" )) ||
- (!strcmp(name, "randomv")) ||
- (!strcmp(name, "entnum")) ||
- (!strcmp(name, "_")) ) //intrinsics, any old function with no args will do.
- {
- intrinsic.name = name;
- intrinsic.type = type_function; // can't put that in the static var
- od = d = &intrinsic;
- }
- else if (keyword_class && !strcmp(name, "this"))
- {
- if (!pr_classtype)
- QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
- od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
- od = d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false);
- }
- else if (keyword_class && !strcmp(name, "super"))
- {
- if (!pr_classtype)
- QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
- od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
- od = d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false);
- }
- else
- {
- od = d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false);
- if (!d)
- QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
- else
+ if (!idx && d->type->type == ev_pointer)
{
- QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
+ /*no bounds checks on pointer dereferences*/
}
- }
- }
-
-reloop:
-
-
-//FIXME: Make this work with double arrays/2nd level structures.
-//Should they just jump back to here?
- if (QCC_PR_CheckToken("["))
- {
- QCC_type_t *newtype;
- if (ao)
- {
- numstatements--; //remove the last statement
-
- nd = QCC_PR_Expression (TOP_PRIORITY, 0);
- QCC_PR_Expect("]");
-
- if (d->type->size != 1) //we need to multiply it to find the offset.
+ else if (!idx && d->type->type == ev_string && !d->arraysize)
{
- if (ao->type->type == ev_integer)
- nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], nd, QCC_MakeIntDef(d->type->size), NULL); //get add part
- else if (ao->type->type == ev_float)
- nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], nd, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
- else
+ /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/
+ }
+ else if (!idx && d->type->type == ev_vector && !d->arraysize)
+ {
+ if (tmp->constant)
{
- QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
- nd = NULL;
+ unsigned int i;
+ if (tmp->type->type == ev_integer)
+ i = G_INT(tmp->ofs);
+ else if (tmp->type->type == ev_float)
+ i = G_FLOAT(tmp->ofs);
+ if (i < 0 || i >= 3)
+ QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds");
}
+ else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
+ {
+ tmp = QCC_SupplyConversion(tmp, ev_integer, true);
+ QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false);
+ }
+ t = type_float;
}
-
- if (nd->type->type == ao->type->type)
+ else if (!((!idx)?d->arraysize:t->arraysize))
{
- if (ao->type->type == ev_integer)
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
- else if (ao->type->type == ev_float)
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], ao, nd, NULL); //get add part
- else
+ QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array");
+ }
+ else if (tmp->constant)
+ {
+ unsigned int i;
+ if (tmp->type->type == ev_integer)
+ i = G_INT(tmp->ofs);
+ else if (tmp->type->type == ev_float)
+ i = G_FLOAT(tmp->ofs);
+ if (i < 0 || i >= ((!idx)?d->arraysize:t->arraysize))
+ QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds");
+ }
+ else
+ {
+ if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
{
- QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
- nd = NULL;
+ tmp = QCC_SupplyConversion(tmp, ev_integer, true);
+ QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false);
}
}
- else
+ if (t->size != 1 && (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))) /*don't multiply by type size if the instruction/emulation will do that instead*/
{
- if (nd->type->type == ev_float)
- nd = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], nd, 0, NULL);
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
+ if (tmp->type->type == ev_float)
+ tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL);
+ else
+ tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL);
}
- newtype = d->type;
- d = od;
+ /*calc the new index*/
+ if (idx)
+ idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL);
+ else
+ idx = tmp;
}
- else
+ else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
{
- ao = QCC_PR_Expression (TOP_PRIORITY, 0);
- QCC_PR_Expect("]");
+ if (!idx && t->type == ev_pointer && !d->arraysize)
+ t = t->aux_type;
- if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1) //we need to multiply it to find the offset.
+ for (t = t->param; t; t = t->next)
{
- if (ao->type->type == ev_integer)
- ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(d->type->size), NULL); //get add part
- else if (ao->type->type == ev_float)
- ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], ao, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
- else
+ if (QCC_PR_CheckName(t->name))
{
- nd = NULL;
- QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
+ break;
}
+
}
+ if (!t)
+ QCC_PR_ParseError(0, "%s is not a member", pr_token);
- newtype = d->type;
+ tmp = QCC_MakeIntConst(t->ofs);
+ if (idx)
+ idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL);
+ else
+ idx = tmp;
}
- if (ao->type->type == ev_integer)
+ else
+ break;
+ }
+
+ if (idx)
+ {
+ if (d->type->type == ev_pointer)
{
- switch(newtype->type)
+ switch (t->type)
{
+ case ev_pointer:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def.
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_integer:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_string:
- if (d->arraysize <= 1)
- {
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], ao, 0, NULL), NULL); //get pointer to precise def.
- newtype = nd->type;//don't be fooled
- }
- else
- {
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def.
- }
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_field:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_function:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type;
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_struct:
+ case ev_union:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
+
+ default:
+ QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
+ }
+ d->type = t;
+ }
+ else if (d->type->type == ev_string && d->arraysize == 0)
+ {
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL);
+ }
+ else if (d->type->type == ev_vector && d->arraysize == 0)
+ {
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ d->type = type_float;
+ }
+ else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
+ {
+ /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/
+ /*source type is a struct, or its an array, or something that can otherwise be directly accessed*/
+ switch(t->type)
+ {
case ev_pointer:
- if (ao->constant && !G_INT(ao->ofs))
- ao->ofs = 0;
- if (d->arraysize>1) //use the array
- {
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- }
- else
- { //dereference the pointer.
- switch(newtype->aux_type->type)
- {
- case ev_pointer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
- }
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_float:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_string:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_vector:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_entity:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_field:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+ break;
+ case ev_function:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
case ev_struct:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
- nd->type = d->type;
+ case ev_union:
+ //FIXME...
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_STRUCT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
break;
default:
QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
}
- d=nd;
+ d->type = t;
}
- else if (ao->type->type == ev_float)
+ else if (idx->constant)
{
- if (qcc_targetformat == QCF_HEXEN2)
- { //hexen2 style retrieval, mixed with q1 style assignments...
- if (QCC_PR_CheckToken("=")) //(hideous concept)
- {
- QCC_def_t *funcretr;
- QCC_def_t *args[2];
- if (d->scope)
- QCC_PR_ParseError(0, "Scoped array without specific engine support");
-
- funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
- nd = QCC_PR_Expression(TOP_PRIORITY, 0);
- if (nd->type->type != d->type->type)
- QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
-
- args[0] = ao;
- args[1] = nd;
- return QCC_PR_GenerateFunctionCall(funcretr, args, 2);
- }
-
- switch(newtype->type)
- {
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, ao, &st); //get pointer to precise def.
- st->a = d->ofs;
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, ao, &st); //get pointer to precise def.
- st->a = d->ofs;
- break;
- case ev_string:
- nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, ao, &st); //get pointer to precise def.
- st->a = d->ofs;
- break;
- case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, ao, &st); //get pointer to precise def.
- st->a = d->ofs;
- break;
- case ev_function:
- nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, ao, &st); //get pointer to precise def.
- st->a = d->ofs;
- break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
- QCC_FreeTemp(d);
- QCC_FreeTemp(ao);
+ int cidx;
+ idx = QCC_SupplyConversion(idx, ev_integer, true);
+ cidx = G_INT(idx->ofs);
- d=nd;
- d->type = newtype;
- return d;
- }
- else
- {
- if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //q1 compatible.
- { //you didn't see this, okay?
- QCC_def_t *funcretr;
- if (d->scope)
- QCC_PR_ParseError(0, "Scoped array without specific engine support");
+ d->references++;
+ tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memcpy (tmp, d, sizeof(QCC_def_t));
+ tmp->arraysize = 0;
+ tmp->ofs = d->ofs + (cidx * type_size[d->type->type]);
+ d = tmp;
- if (allowarrayassign && QCC_PR_CheckToken("="))
- {
- QCC_def_t *args[2];
+ //d can be assigned to freely
+ }
+ else if (allowarrayassign && QCC_PR_CheckToken("="))
+ {
+ /*if its assigned to, generate a functioncall to do the store*/
+ QCC_def_t *args[2], *funcretr, *rhs;
- funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
+ d->references++;
+ funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 0, false);
- nd = QCC_PR_Expression(TOP_PRIORITY, 0);
- if (nd->type->type != d->type->type)
- QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
+ rhs = QCC_PR_Expression(TOP_PRIORITY, 0);
+ if (rhs->type->type != d->type->type)
+ QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
- args[0] = ao;
- args[1] = nd;
- qcc_usefulstatement=true;
- nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
- nd->type = d->type->aux_type;
- }
- else
- {
- QCC_def_t *args[1];
-
- def_parms[0].type = type_float;
- funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false);
+ args[0] = QCC_SupplyConversion(idx, ev_float, true);
+ args[1] = rhs;
+ qcc_usefulstatement=true;
+ d = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
+ d->type = t;
- args[0] = ao;
- nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
- nd->type = d->type->aux_type;
- }
- }
- else
- {
- switch(newtype->type)
- {
- case ev_pointer:
- if (d->arraysize>1) //use the array
- {
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- }
- else
- { //dereference the pointer.
- switch(newtype->aux_type->type)
- {
- case ev_pointer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type->aux_type;
- break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
- }
- break;
+ return d;
+ }
+ else if (QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F]))
+ {
+ if (!d->arraysize)
+ QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on non-array");
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
- case ev_string:
- if (d->arraysize <= 1)
- {
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, ao, NULL); //get pointer to precise def.
- newtype = nd->type;//don't be fooled
- }
- else
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
- case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
- case ev_field:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
- case ev_function:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type;
- break;
- case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- break;
+ if (d->temp)
+ QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on a temp");
- case ev_struct:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
- nd->type = d->type;
- break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
- }
+ /*hexen2 format has opcodes to read arrays (but has no way to write)*/
+ switch(t->type)
+ {
+ case ev_float:
+ d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+// st->a = d->ofs;
+ break;
+ case ev_vector:
+ d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+// st->a = d->ofs;
+ break;
+ case ev_string:
+ d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+// st->a = d->ofs;
+ break;
+ case ev_entity:
+ d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+// st->a = d->ofs;
+ break;
+ case ev_function:
+ d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+// st->a = d->ofs;
+ break;
+ default:
+ QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
+ d = NULL;
+ break;
}
- d=nd;
+ d->type = t;
}
else
- QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
-
- d->type = newtype;
- goto reloop;
- }
+ {
+ /*emulate the array access using a function call to do the read for us*/
+ QCC_def_t *args[1], *funcretr;
+ d->references++;
- i = d->type->type;
- if (i == ev_pointer)
- {
- int j;
- QCC_type_t *type;
- if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
- {
- for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
- {
- if (QCC_PR_CheckName(type->name))
- {
- //give result
- if (ao)
- {
- numstatements--; //remove the last statement
- d = od;
+ /*make sure the function type that we're calling exists*/
+ def_parms[0].type = type_float;
+ funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false);
- nd = QCC_MakeIntDef(type->ofs);
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
+ args[0] = QCC_SupplyConversion(idx, ev_float, true);
+ d = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
+ d->type = t;
+ }
- //so that we may offset it and readd it.
- }
- else
- ao = QCC_MakeIntDef(type->ofs);
- switch (type->type)
- {
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_string:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_field:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_function:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, ao, NULL); //get pointer to precise def.
- nd->type = type;
- break;
- case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
- break;
+ /*parse recursively*/
+ d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
+ }
-// case ev_struct:
- //no suitable op.
-// nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
-// nd->type = type;
-// break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
+ return d;
+}
- d=nd;
- break;
- }
- if (type->num_parms)
- {
- for (j = type->num_parms; j;j--)
- type++;
- }
- }
- if (!i)
- QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
+/*
+============
+PR_ParseValue
- goto reloop;
- }
- }
- else if (i == ev_struct || i == ev_union)
- {
- int j;
- QCC_type_t *type;
- if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
- {
- for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
- {
- if (QCC_PR_CheckName(type->name))
- {
- //give result
- if (ao)
- {
- numstatements--; //remove the last statement
- d = od;
+Returns the global ofs for the current token
+============
+*/
+QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
+{
+ QCC_def_t *d, *od, *tmp;
+ QCC_type_t *t;
+ char *name;
- nd = QCC_MakeIntDef(type->ofs);
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
+ char membername[2048];
- //so that we may offset it and readd it.
- }
- else
- ao = QCC_MakeIntDef(type->ofs);
- switch (type->type)
- {
- case ev_float:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_string:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_vector:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_field:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
- break;
- case ev_function:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def.
- nd->type = type;
- break;
- case ev_integer:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
- break;
+// if the token is an immediate, allocate a constant for it
+ if (pr_token_type == tt_immediate)
+ return QCC_PR_ParseImmediate ();
-// case ev_struct:
- //no suitable op.
-// nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
-// nd->type = type;
-// break;
- default:
- QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
- nd = NULL;
- break;
- }
+ if (QCC_PR_CheckToken("[")) //reacc support
+ { //looks like a funky vector. :)
+ vec3_t v;
+ pr_immediate_type = type_vector;
+ v[0] = pr_immediate._float;
+ QCC_PR_Lex();
+ v[1] = pr_immediate._float;
+ QCC_PR_Lex();
+ v[2] = pr_immediate._float;
+ pr_immediate.vector[0] = v[0];
+ pr_immediate.vector[1] = v[1];
+ pr_immediate.vector[2] = v[2];
+ pr_immediate_type = type_vector;
+ d = QCC_PR_ParseImmediate();
+ QCC_PR_Expect("]");
+ return d;
+ }
+ name = QCC_PR_ParseName ();
- d=nd;
- break;
- }
- if (type->num_parms)
- {
- for (j = type->num_parms; j;j--)
- type++;
- }
- }
- if (!i)
- QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
+ if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar'
+ { //try getting a member.
+ QCC_type_t *type;
+ type = assumeclass;
+ d = NULL;
+ while(type != type_entity && type)
+ {
+ sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
+ d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
+ if (d)
+ break;
- goto reloop;
+ type = type->parentclass;
}
+ if (!d)
+ d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
+ }
+ else
+ {
+ // look through the defs
+ d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
}
-/* if (d->type->type == ev_pointer)
- { //expand now, not in function call/maths parsing
- switch(d->type->aux_type->type)
+ if (!d)
+ {
+ if ( (!strcmp(name, "random" )) ||
+ (!strcmp(name, "randomv")) ||
+ (!strcmp(name, "sizeof")) ||
+ (!strcmp(name, "entnum")) ||
+ (!strcmp(name, "_"))) //intrinsics, any old function with no args will do.
{
- case ev_string:
- d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, NULL, NULL);
- break;
- case ev_float:
- d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, NULL, NULL);
- break;
+ d = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
+ d->initialized = 0;
+ }
+ else if (keyword_class && !strcmp(name, "this"))
+ {
+ if (!pr_classtype)
+ QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
+ od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
+ d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 0, od->ofs, true, false);
+ }
+ else if (keyword_class && !strcmp(name, "super"))
+ {
+ if (!pr_classtype)
+ QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
+ od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
+ d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 0, od->ofs, true, false);
+ }
+ else
+ {
+ d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 0, false);
+ if (!d)
+ QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
+ else
+ {
+ QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
+ }
}
}
-*/
- if (!keyword_class)
- return d;
- if (d->type->parentclass||d->type->type == ev_entity) //class
+ d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
+
+ t = d->type;
+ if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
{
- if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
+ QCC_def_t *field;
+ if (QCC_PR_CheckToken("("))
{
- QCC_def_t *field;
- if (QCC_PR_CheckToken("("))
+ field = QCC_PR_Expression(TOP_PRIORITY, 0);
+ QCC_PR_Expect(")");
+ }
+ else
+ field = QCC_PR_ParseValue(d->type, false);
+ if (field->type->type == ev_field)
+ {
+ if (!field->type->aux_type)
{
- field = QCC_PR_Expression(TOP_PRIORITY, 0);
- QCC_PR_Expect(")");
+ QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
}
else
- field = QCC_PR_ParseValue(d->type, false);
- if (field->type->type == ev_field)
- {
- if (!field->type->aux_type)
- {
- QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
- }
- else
- {
- switch(field->type->aux_type->type)
- {
- default:
- QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
- return d;
- case ev_integer:
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
- case ev_field:
- d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
- nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (nd, 0, sizeof(QCC_def_t));
- nd->type = field->type->aux_type;
- nd->ofs = d->ofs;
- nd->temp = d->temp;
- nd->constant = false;
- nd->name = d->name;
- return nd;
- case ev_float:
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
- case ev_string:
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
- case ev_vector:
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
- case ev_function:
- { //complicated for a typecast
- d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
- nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (nd, 0, sizeof(QCC_def_t));
- nd->type = field->type->aux_type;
- nd->ofs = d->ofs;
- nd->temp = d->temp;
- nd->constant = false;
- nd->name = d->name;
- return nd;
-
- }
- case ev_entity:
- return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
- }
+ {
+ switch(field->type->aux_type->type)
+ {
+ default:
+ QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
+ break;
+ case ev_integer:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
+ break;
+ case ev_field:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
+ tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (tmp, 0, sizeof(QCC_def_t));
+ tmp->type = field->type->aux_type;
+ tmp->ofs = d->ofs;
+ tmp->temp = d->temp;
+ tmp->constant = false;
+ tmp->name = d->name;
+ d = tmp;
+ break;
+ case ev_float:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
+ break;
+ case ev_string:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
+ break;
+ case ev_vector:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
+ break;
+ case ev_function:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
+ tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (tmp, 0, sizeof(QCC_def_t));
+ tmp->type = field->type->aux_type;
+ tmp->ofs = d->ofs;
+ tmp->temp = d->temp;
+ tmp->constant = false;
+ tmp->name = d->name;
+ d = tmp;
+ break;
+ case ev_entity:
+ d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
+ break;
}
}
- else
- QCC_PR_IncludeChunk(".", false, NULL);
}
+ else
+ QCC_PR_IncludeChunk(".", false, NULL);
}
return d;
switch (e->type->type)
{
case ev_integer:
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
break;
case ev_float:
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
break;
default:
QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "++ operator on unsupported type");
switch (e->type->type)
{
case ev_integer:
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
break;
case ev_float:
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
break;
default:
QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "-- operator on unsupported type");
else if (QCC_PR_CheckToken ("&"))
{
int st = numstatements;
- e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+ e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
t = e->type->type;
if (st != numstatements)
//woo, something like ent.field?
{
- if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
+ if ((OP_LOAD_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOAD_FNC) || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
{
statements[numstatements-1].op = OP_ADDRESS;
e->type = QCC_PR_PointerType(e->type);
return e;
}
+ else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I)
+ {
+ statements[numstatements-1].op = OP_GLOBALADDRESS;
+ e->type = QCC_PR_PointerType(e->type);
+ return e;
+ }
+ else if (OP_LOADP_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADP_I)
+ {
+ statements[numstatements-1].op = OP_POINTER_ADD;
+ e->type = QCC_PR_PointerType(e->type);
+ return e;
+ }
else //this is a restriction that could be lifted, I just want to make sure that I got all the bits first.
{
QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference");
}
else if (QCC_PR_CheckToken ("*"))
{
- e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+ e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
t = e->type->type;
- if (t != ev_pointer)
- QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
-
- switch(e->type->aux_type->type)
+ if (t == ev_string)
+ e2 = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], e, QCC_MakeFloatConst(0), NULL);
+ else if (t == ev_pointer)
{
- case ev_float:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
- break;
- case ev_string:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
- break;
- case ev_vector:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
- break;
- case ev_entity:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
- break;
- case ev_field:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
- break;
- case ev_function:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
- break;
- case ev_integer:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
- break;
- case ev_pointer:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
- break;
+ switch(e->type->aux_type->type)
+ {
+ case ev_float:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
+ break;
+ case ev_string:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
+ break;
+ case ev_vector:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
+ break;
+ case ev_entity:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
+ break;
+ case ev_field:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
+ break;
+ case ev_function:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
+ break;
+ case ev_integer:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
+ break;
+ case ev_pointer:
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
+ break;
- default:
- QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
- e2 = NULL;
- break;
+ default:
+ QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
+ e2 = NULL;
+ break;
+ }
+ e2->type = e->type->aux_type;
}
-
- e2->type = e->type->aux_type;
+ else
+ QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
return e2;
}
else if (QCC_PR_CheckToken ("-"))
{
- e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+ e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
switch(e->type->type)
{
case ev_float:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatDef(0), e, NULL);
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), e, NULL);
break;
case ev_vector:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorDef(0, 0, 0), e, NULL);
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorConst(0, 0, 0), e, NULL);
break;
case ev_integer:
- e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntDef(0), e, NULL);
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntConst(0), e, NULL);
break;
default:
QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for -");
}
else if (QCC_PR_CheckToken ("+"))
{
- e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+ e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
switch(e->type->type)
{
if (QCC_PR_CheckToken ("("))
{
- if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts
+ QCC_type_t *newtype;
+ newtype = QCC_PR_ParseType(false, true);
+ if (newtype)
+ {
+ QCC_PR_Expect (")");
+ e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
+
+ /*you may cast from a type to itself*/
+ if (!typecmp(e->type, newtype))
+ {
+ }
+ /*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/
+ else if (newtype->size == e->type->size && (e->type->type == ev_integer || e->type->type == ev_float) && e->constant && !G_INT(e->ofs))
+ {
+ //direct cast
+ e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (e2, 0, sizeof(QCC_def_t));
+
+ e2->type = newtype;
+ e2->ofs = e->ofs;
+ e2->constant = true;
+ e2->temp = e->temp;
+ return e2;
+ }
+ /*cast from int->float will convert*/
+ else if (newtype->type == ev_float && e->type->type == ev_integer)
+ return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL);
+ /*cast from float->int will convert*/
+ else if (newtype->type == ev_integer && e->type->type == ev_float)
+ return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
+ /*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
+ else if (
+ //pointers
+ ((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer))
+ //ents/classs
+ || (newtype->type == ev_entity && e->type->type == ev_entity)
+ //variants are fine too
+ || (newtype->type == ev_variant || e->type->type == ev_variant)
+ )
+ {
+ //direct cast
+ e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (e2, 0, sizeof(QCC_def_t));
+
+ e2->type = newtype;
+ e2->ofs = e->ofs;
+ e2->constant = true;
+ e2->temp = e->temp;
+ return e2;
+ }
+ else
+ QCC_PR_ParseError(0, "Bad type cast\n");
+ }
+/* else if (QCC_PR_CheckToken("*"))
+ {
+ QCC_PR_Expect (")");
+ e = QCC_PR_Term();
+ e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+ memset (e2, 0, sizeof(QCC_def_t));
+ e2->type = type_pointer;
+ e2->ofs = e->ofs;
+ e2->constant = true;
+ e2->temp = e->temp;
+ return e2;
+ }
+ else if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts
{
QCC_PR_Expect (")");
e = QCC_PR_Term();
else
QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
}
- else
+*/ else
{
pbool oldcond = conditional;
conditional = conditional?2:0;
}
}
+ if (from->type->type == ev_variant)
+ return 3;
+
/* if (from->type->type == ev_pointer && from->type->aux_type->type == to)
return 1;
if (from->type->type == ev_integer && to == ev_function)
return 1;
+ if (from->constant && from->arraysize == 0 && (from->type->type == ev_integer || from->type->type == ev_float) && !G_INT(from->ofs))
+ return 2;
+
return -100;
}
/*
while (1)
{
- if (priority == 1)
+ if (priority == FUNC_PRIORITY)
{
if (QCC_PR_CheckToken ("(") )
{
if (pr_token_type == tt_immediate)
{
- if (pr_immediate_type->type == ev_float)
- if (pr_immediate._float < 0) //hehehe... was a minus all along...
+ if ((pr_immediate_type->type == ev_float && pr_immediate._float < 0) ||
+ (pr_immediate_type->type == ev_integer && pr_immediate._int < 0)) //hehehe... was a minus all along...
{
QCC_PR_IncludeChunk(pr_token, true, NULL);
strcpy(pr_token, "+");//two negatives would make a positive.
//this kills the add 0.
e->ofs = statements[numstatements-1].a;
numstatements--;
-
- if (e->type->type != ev_pointer)
- {
- type_pointer->aux_type->type = e->type->type;
- e->type = type_pointer;
- }
}
else
{
- statements[numstatements-1].op = OP_ADD_I;
- if (e->type->type != ev_pointer)
- {
- type_pointer->aux_type->type = e->type->type;
- e->type = type_pointer;
- }
+ statements[numstatements-1].op = OP_POINTER_ADD;
+ }
+ if (e->type != type_pointer)
+ {
+ type_pointer->aux_type->type = e->type->type;
+ e->type = type_pointer;
}
}
if ( !simplestore && statements[numstatements-1].op == OP_LOADP_C && e->ofs == statements[numstatements-1].c)
{//assignment
if (op->type_a == &type_pointer) //ent var
{
+ /*FIXME: I don't like this code*/
if (e->type->type != ev_pointer)
c = -200; //don't cast to a pointer.
else if ((*op->type_c)->type == ev_void && op->type_b == &type_pointer && e2->type->type == ev_pointer)
c=QCC_canConv(e2, (*op->type_b)->type);
if (type_a != (*op->type_a)->type) //in this case, a is the final assigned value
c = -300; //don't use this op, as we must not change var b's type
+ else if ((*op->type_a)->type == ev_pointer && e->type->aux_type->type != (*op->type_a)->aux_type->type)
+ c = -300; //don't use this op if its a pointer to a different type
}
}
else
QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
if (e->type->type == ev_float)
{
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e2, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e2, false);
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
}
else if (e->type->type == ev_integer)
{
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e2, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e2, false);
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
}
else
e2 = QCC_GetTemp(type_float);
QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
QCC_FreeTemp(e);
e = e2;
}
e2 = QCC_GetTemp(type_integer);
QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
- QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
QCC_FreeTemp(e);
e = e2;
}
QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
if (e->type->type == ev_float)
{
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e2, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e2, false);
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
}
else if (e->type->type == ev_integer)
{
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e2, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e2, false);
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
}
else
e2 = QCC_GetTemp(type_float);
QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
QCC_FreeTemp(e);
e = e2;
}
e2 = QCC_GetTemp(type_integer);
QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
- QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
QCC_FreeTemp(e);
e = e2;
}
if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (","))
{
+ if (!qcc_usefulstatement)
+ QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement");
+
QCC_FreeTemp(e);
- return QCC_PR_Expression(TOP_PRIORITY, exprflags);
+ qcc_usefulstatement = false;
+ e = QCC_PR_Expression(TOP_PRIORITY, exprflags);
}
return e;
}
+int QCC_PR_IntConstExpr(void)
+{
+ QCC_def_t *def = QCC_PR_Expression(TOP_PRIORITY, 0);
+ if (def->constant)
+ {
+ def->references++;
+ if (def->type->type == ev_integer)
+ return G_INT(def->ofs);
+ if (def->type->type == ev_float)
+ {
+ int i = G_FLOAT(def->ofs);
+ if ((float)i == G_FLOAT(def->ofs))
+ return i;
+ }
+ }
+ QCC_PR_ParseError(ERR_NOTACONSTANT, "Value is not an integer constant");
+ return true;
+}
+
void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname)
{
if (num_gotos >= max_gotos)
{
e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
}*/
if (QCC_PR_CheckToken (";"))
return;
}
e = QCC_PR_Expression (TOP_PRIORITY, 0);
- e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type);
+ e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type, true);
if (e != e2)
{
QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
float frame = pr_immediate._float;
QCC_PR_Lex();
name = QCC_PR_ParseName();
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatDef(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatConst(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
QCC_PR_Expect(";");
return;
}
if (pr_casesdef[i]->type->type != e->type->type)
{
if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
- pr_casesdef[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
+ pr_casesdef[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
else
QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch case type mismatch");
}
if (pr_casesdef2[i]->type->type != e->type->type)
{
if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
- pr_casesdef2[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
+ pr_casesdef2[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
else
QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange type mismatch");
}
frame = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], self, framef, NULL);
if (cycle_wrapped)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(0), cycle_wrapped, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(0), cycle_wrapped, NULL));
QCC_UnFreeTemp(frame);
//make sure the frame is within the bounds given.
t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL);
QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 7, 0, false);
QCC_FreeTemp(t1); //this block is the 'it's in a forwards direction'
- QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
+ QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
QCC_UnFreeTemp(frame);
if (cycle_wrapped)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
//reverse animation.
- QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
+ QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
QCC_UnFreeTemp(frame);
if (cycle_wrapped)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
//self.frame = frame happens with the normal state opcode.
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], frame, pr_scope, NULL));
name = QCC_PR_ParseName ();
pr_scope = NULL;
- def = QCC_PR_GetDef (type_function, name, NULL, true, 1, false);
+ def = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
pr_scope = sc;
QCC_PR_Expect ("]");
{
QCC_def_t *local;
unsigned int newofs;
+ int size;
// if (!opt_overlaptemps) //clear these after each function. we arn't overlapping them so why do we need to keep track of them?
// {
if (local->constant)
continue;
- newofs += local->type->size*local->arraysize;
- if (local->arraysize>1)
- newofs++;
+ size = local->type->size*(local->arraysize?local->arraysize:1);
+ if (local->arraysize)
+ size++;
+
+ newofs += size;
}
locals_start = MAX_REGS;
if (((int*)qcc_pr_globals)[local->ofs])
QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value");
- newofs -= local->type->size*local->arraysize;
- if (local->arraysize>1)
- newofs--;
+ size = local->type->size*(local->arraysize?local->arraysize:1);
+ if (local->arraysize)
+ size++;
+
+ newofs -= size;
- QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+local->type->size*local->arraysize, newofs);
- QCC_FreeOffset(local->ofs, local->type->size*local->arraysize);
+ QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+size, newofs);
+ QCC_FreeOffset(local->ofs, size);
local->ofs = newofs;
}
break;
}
if (param)
- fprintf(asmfile, "%s %s /* at %d */", TypeName(type), param->name, o);
+ fprintf(asmfile, "%s %s", TypeName(type), param->name);
else
- fprintf(asmfile, "%s /* at %d */", TypeName(type), o);
+ fprintf(asmfile, "%s", TypeName(type));
o += type->size;
}
}
}
}
- fprintf(asmfile, ";\n");
+ fprintf(asmfile, "; /*%i*/\n", statement_linenums[i]);
}
fprintf(asmfile, "}\n\n");
{
if (!*pr_parm_names[i])
QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
- defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 1, false);
+ defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 0, false);
defs[i]->references++;
if (i < MAX_PARMS)
/*if (pr_classtype)
{
QCC_def_t *e, *e2;
- e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 1);
- e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 1);
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), e, NULL));
+ e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 0);
+ e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 0);
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), e, NULL));
}*/
//
do {
name = QCC_PR_ParseName();
QCC_PR_Expect(":");
- e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1, false);
+ e2 = QCC_PR_GetDef(QCC_PR_ParseType(false, false), name, pr_scope, true, 0, false);
QCC_PR_Expect(";");
} while(!QCC_PR_CheckToken("{"));
}
QCC_def_t *e, *e2;
e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
}*/
QCC_PR_Statement (pr_opcodes, 0,0, NULL);
QCC_def_t *eq;
if (min == max || min+1 == max)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
QCC_def_t *eq;
if (min == max || min+1 == max)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
QCC_dfunction_t *df;
QCC_def_t *temp, *index, *func;
- func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 1, false);
+ func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false);
pr_scope = func;
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
+
df = &functions[numfunctions];
numfunctions++;
df->parm_size[0] = 1;
df->numparms = 1;
df->parm_start = numpr_globals;
- index = QCC_PR_GetDef(type_float, "index___", func, true, 1, false);
+ index = QCC_PR_GetDef(type_float, "index___", func, true, 0, false);
index->references++;
- temp = QCC_PR_GetDef(type_float, "div3___", func, true, 1, false);
+ temp = QCC_PR_GetDef(type_float, "div3___", func, true, 0, false);
locals_end = numpr_globals;
df->locals = locals_end - df->parm_start;
- QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp, false);
+ QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), temp, false);
QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int
QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up
- QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL); //err... we didn't find it, give up.
+ QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); //err... we didn't find it, give up.
QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); //err... we didn't find it, give up.
G_FUNCTION(func->ofs) = df - functions;
QCC_def_t *fasttrackpossible;
if (flag_fasttrackarrays)
- fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
+ fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
else
fasttrackpossible = NULL;
pr_scope = scope;
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
+
df = &functions[numfunctions];
numfunctions++;
df->parm_size[0] = 1;
df->numparms = 1;
df->parm_start = numpr_globals;
- index = QCC_PR_GetDef(type_float, "indexg___", def, true, 1, false);
+ index = QCC_PR_GetDef(type_float, "indexg___", def, true, 0, false);
G_FUNCTION(scope->ofs) = df - functions;
//we need to work out which part, x/y/z that it's stored in.
//0,1,2 = i - ((int)i/3 *) 3;
- div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false);
- intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false);
+ div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false);
+ intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false);
- eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
+ eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
- QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st);
+ QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, &st);
div3->references++;
QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
- QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), div3, false);
+ QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), div3, false);
QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, div3, div3, intdiv3, false);
QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false);
QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false);
vectortrick->references++;
- ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1, false);
+ ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 0, false);
ret->references+=4;
QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false);
QCC_FreeTemp(&def_ret);
- div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatDef(3), NULL);
+ div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatConst(3), NULL);
QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
QCC_FreeTemp(div3);
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(0+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(0+0.5f), NULL);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 0;
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(1+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(1+0.5f), NULL);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 1;
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(2+0.5), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(2+0.5), NULL);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize);
}
- QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL);
+ QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL);
QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
QCC_def_t *eq;
if (min == max || min+1 == max)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatConst((float)min), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 3;
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef((float)mid), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst((float)mid), NULL);
QCC_UnFreeTemp(index);
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
QCC_def_t *fasttrackpossible;
if (flag_fasttrackarrays)
- fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
+ fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
else
fasttrackpossible = NULL;
def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
pr_scope = scope;
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
+
df = &functions[numfunctions];
numfunctions++;
df->parm_size[1] = def->type->size;
df->numparms = 2;
df->parm_start = numpr_globals;
- index = QCC_PR_GetDef(type_float, "indexs___", def, true, 1, false);
- value = QCC_PR_GetDef(def->type, "value___", def, true, 1, false);
+ index = QCC_PR_GetDef(type_float, "indexs___", def, true, 0, false);
+ value = QCC_PR_GetDef(def->type, "value___", def, true, 0, false);
locals_end = numpr_globals;
df->locals = locals_end - df->parm_start;
QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats
QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p
if (def->type->size != 1)//shift it upwards for larger types
- QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntDef(def->type->size), index, true);
+ QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(def->type->size), index, true);
QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add
if (def->type->size >= 3)
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true); //*b = a
KEYWORD(asm);
}
- for (a = 0; a < arraysize; a++)
+ for (a = 0; a < (arraysize?arraysize:1); a++)
{
if (a == 0)
*array = '\0';
def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
memset (def, 0, sizeof(*def));
def->next = NULL;
- def->arraysize = arraysize;
+ def->arraysize = a?0:arraysize;
if (name)
{
pr.def_tail->next = def;
def->s_line = pr_source_line;
def->s_file = s_file;
+ if (a)
+ def->initialized = 1;
def->name = (void *)qccHunkAlloc (strlen(newname)+1);
strcpy (def->name, newname);
def->scope = scope;
def->saved = saved;
- // if (arraysize>1)
+ //if (type->type = ev_field)
def->constant = true;
if (ofs + type->size*a >= MAX_REGS)
{
case ev_vector:
sprintf(newname, "%s%s.%s", name, array, parttype->name);
- QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
+ QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
sprintf(newname, "%s%s.%s_x", name, array, parttype->name);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, false);
sprintf(newname, "%s%s.%s_y", name, array, parttype->name);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+1, false, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+1, false, false);
sprintf(newname, "%s%s.%s_z", name, array, parttype->name);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+2, false, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+2, false, false);
break;
case ev_float:
case ev_union:
case ev_variant: //for lack of any better alternative
sprintf(newname, "%s%s.%s", name, array, parttype->name);
- QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
+ QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
break;
case ev_function:
sprintf(newname, "%s%s.%s", name, array, parttype->name);
- QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
+ QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
break;
case ev_void:
break;
else if (type->type == ev_vector)
{ //do the vector thing.
sprintf(newname, "%s%s_x", name, array);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+0, referable, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, false);
sprintf(newname, "%s%s_y", name, array);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+1, referable, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, false);
sprintf(newname, "%s%s_z", name, array);
- QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+2, referable, false);
+ QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, false);
}
else if (type->type == ev_field)
{
{
//do the vector thing.
sprintf(newname, "%s%s_x", name, array);
- QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+0, referable, false);
+ QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+0, referable, false);
sprintf(newname, "%s%s_y", name, array);
- QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+1, referable, false);
+ QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, false);
sprintf(newname, "%s%s_z", name, array);
- QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+2, referable, false);
+ QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, false);
}
}
+ first->deftail = pr.def_tail;
}
if (referable)
{
if (!pHash_Get(&globalstable, "end_sys_fields"))
first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off.
- if (arraysize <= 1 && first->type->type != ev_field)
+ if (!arraysize && first->type->type != ev_field)
first->constant = false;
if (scope)
pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
if (!scope && asmfile)
- fprintf(asmfile, "%s %s; /* at %d */\n", TypeName(first->type), first->name, first->ofs);
+ fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
}
return first;
If type is NULL, it will match any type
If allocate is true, a new def will be allocated if it can't be found
+If arraysize=0, its not an array and has 1 element.
+If arraysize>0, its an array and requires array notation
+If arraysize<0, its an array with undefined size - GetDef will fail if its not already allocated.
============
*/
unsigned int i;
QCC_def_t *foundstatic = NULL;
+ if (!allocate)
+ arraysize = -1;
+
if (scope)
{
def = Hash_Get(&localstable, name);
if (type && typecmp(def->type, type))
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
- if (def->arraysize != arraysize && arraysize)
+ if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
if (!pr_scope)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
}
- if (def->arraysize != arraysize && arraysize)
+ if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
if (type && typecmp(def->type, type))
QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
- if (def->arraysize != arraysize && arraysize)
+ if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
if (!pr_scope)
QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
}
- if (def->arraysize != arraysize && arraysize)
+ if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
if (!allocate)
return NULL;
- if (arraysize < 1)
+ if (arraysize < 0)
{
QCC_PR_ParseError (ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name);
}
}
ofs = numpr_globals;
- if (arraysize > 1)
+ if (arraysize)
{ //write the array size
ofs = QCC_GetFreeOffsetSpace(1 + (type->size * arraysize));
ofs++;
}
else
- ofs = QCC_GetFreeOffsetSpace(type->size * arraysize);
+ ofs = QCC_GetFreeOffsetSpace(type->size);
def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, true, saved);
//fix up fields.
if (type->type == ev_field && allocate != 2)
{
- for (i = 0; i < type->size*arraysize; i++) //make arrays of fields work.
+ for (i = 0; i < type->size*(arraysize?arraysize:1); i++) //make arrays of fields work.
*(int *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i;
pr.size_fields += i;
startfield = *fieldofs;
maxfield = startfield;
- for (a = 0; a < arraysize; a++)
+ for (a = 0; a < (arraysize?arraysize:1); a++)
{
if (a == 0)
*array = '\0';
sprintf(newname, "%s%s.%s", name, array, parttype->name);
else
sprintf(newname, "%s%s", parttype->name, array);
- ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
+ ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
ftype->aux_type = parttype;
if (parttype->type == ev_vector)
ftype->size = parttype->size; //vector fields create a _y and _z too, so we need this still.
- def = QCC_PR_GetDef(NULL, newname, scope, false, 1, saved);
+ def = QCC_PR_GetDef(NULL, newname, scope, false, 0, saved);
if (!def)
{
- def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
+ def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
}
else
{
sprintf(newname, "%s%s.%s", name, array, parttype->name);
else
sprintf(newname, "%s%s", parttype->name, array);
- ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
+ ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
ftype->aux_type = parttype;
- def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
+ def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
def->initialized = true;
((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
*fieldofs += parttype->size;
QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields, true);
}
+
+void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type, int offset)
+{
+ QCC_def_t *tmp;
+ int i;
+
+ if (arraysize)
+ {
+ //arrays go recursive
+ QCC_PR_Expect("{");
+ for (i = 0; i < arraysize; i++)
+ {
+ QCC_PR_ParseInitializerType(0, def, type, offset + i*type->size);
+ if (!QCC_PR_CheckToken(","))
+ break;
+ }
+ QCC_PR_Expect("}");
+ }
+ else
+ {
+ if (type->type == ev_function && pr_token_type == tt_punct)
+ {
+ /*begin function special case*/
+ QCC_def_t *parentfunc = pr_scope;
+ QCC_function_t *f;
+ QCC_dfunction_t *df;
+ QCC_type_t *parm;
+
+ tmp = NULL;
+
+ def->references++;
+ pr_scope = def;
+ if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":"))
+ {
+ int binum = 0;
+ if (pr_token_type == tt_immediate
+ && pr_immediate_type == type_float
+ && pr_immediate._float == (int)pr_immediate._float)
+ binum = (int)pr_immediate._float;
+ else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer)
+ binum = pr_immediate._int;
+ else
+ QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
+ QCC_PR_Lex();
+
+ if (def->initialized)
+ for (i = 0; i < numfunctions; i++)
+ {
+ if (functions[i].first_statement == -binum)
+ {
+ tmp = QCC_MakeIntConst(i);
+ break;
+ }
+ }
+
+ if (!tmp)
+ {
+ f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
+ f->builtin = binum;
+
+ locals_start = locals_end = OFS_PARM0; //hmm...
+ }
+ else
+ f = NULL;
+ }
+ else
+ f = QCC_PR_ParseImmediateStatements (type);
+ if (!tmp)
+ {
+ pr_scope = parentfunc;
+ tmp = QCC_MakeIntConst(numfunctions);
+ f->def = def;
+
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
+
+ // fill in the dfunction
+ df = &functions[numfunctions];
+ numfunctions++;
+ if (f->builtin)
+ df->first_statement = -f->builtin;
+ else
+ df->first_statement = f->code;
+
+ if (f->builtin && opt_function_names)
+ optres_function_names += strlen(f->def->name);
+ else
+ df->s_name = QCC_CopyString (f->def->name);
+ df->s_file = s_file2;
+ df->numparms = f->def->type->num_parms;
+ df->locals = locals_end - locals_start;
+ df->parm_start = locals_start;
+ for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
+ {
+ df->parm_size[i] = parm->size;
+ }
+ /*end function special case*/
+ }
+ }
+ else if (type->type == ev_string && QCC_PR_CheckName("_"))
+ {
+ char trname[128];
+ QCC_PR_Expect("(");
+ if (pr_token_type != tt_immediate || pr_immediate_type->type != ev_string)
+ QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate");
+ tmp = QCC_MakeStringConst(pr_immediate_string);
+ QCC_PR_Lex();
+ QCC_PR_Expect(")");
+
+ if (!pr_scope || def->constant)
+ {
+ QCC_def_t *dt;
+ sprintf(trname, "dotranslate_%i", ++dotranslate_count);
+ dt = QCC_PR_DummyDef(type_string, trname, pr_scope, 0, offset, true, true);
+ dt->references = 1;
+ dt->constant = 1;
+ dt->initialized = 1;
+ }
+ }
+ else if (type->type == ev_struct || type->type == ev_union)
+ {
+ //structs go recursive
+ QCC_type_t *parttype;
+ int partnum;
+ int parms;
+ pbool isunion;
+ QCC_PR_Expect("{");
+
+ isunion = ((type)->type == ev_union);
+ for (partnum = 0, parttype = (type)->param, parms = (type)->num_parms; partnum < parms; partnum++, parttype = parttype->next)
+ {
+ QCC_PR_ParseInitializerType(parttype->arraysize, def, parttype, offset + parttype->ofs);
+ if (isunion || !QCC_PR_CheckToken(","))
+ break;
+ }
+ QCC_PR_Expect("}");
+ return;
+ }
+ else
+ {
+ tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
+ if (typecmp(type, tmp->type))
+ {
+ /*you can cast from const 0 to anything*/
+ if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs))
+ {
+ }
+ /*cast from int->float will convert*/
+ else if (type->type == ev_float && tmp->type->type == ev_integer)
+ tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], tmp, 0, NULL);
+ /*cast from float->int will convert*/
+ else if (type->type == ev_integer && tmp->type->type == ev_float)
+ tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], tmp, 0, NULL);
+ else
+ QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type");
+ }
+ }
+
+ if (!pr_scope || def->constant)
+ {
+ if (!tmp->constant)
+ QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initializer is not constant");
+
+ if (def->initialized)
+ {
+ for (i = 0; (unsigned)i < type->size; i++)
+ if (G_INT(offset+i) != G_INT(tmp->ofs+i))
+ QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "incompatible redeclaration");
+ }
+ else
+ {
+ for (i = 0; (unsigned)i < type->size; i++)
+ G_INT(offset+i) = G_INT(tmp->ofs+i);
+ }
+ }
+ else
+ {
+ QCC_def_t lhs, rhs;
+ if (def->initialized)
+ QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s initialised twice", def->name);
+
+ memset(&lhs, 0, sizeof(lhs));
+ memset(&rhs, 0, sizeof(rhs));
+ def->references++;
+ for (i = 0; (unsigned)i < type->size; )
+ {
+ rhs.type = lhs.type = type_float;
+ lhs.ofs = offset+i;
+ tmp->references++;
+ rhs.ofs = tmp->ofs+i;
+
+ if (type->size - i >= 3)
+ {
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &rhs, &lhs, NULL));
+ i+=3;
+ }
+ else
+ {
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &rhs, &lhs, NULL));
+ i++;
+ }
+ }
+ }
+ QCC_FreeTemp(tmp);
+ }
+}
+
+void QCC_PR_ParseInitializerDef(QCC_def_t *def, pbool isvar, pbool isconst)
+{
+ def->constant = (isconst || (!isvar && !pr_scope));
+ QCC_PR_ParseInitializerType(def->arraysize, def, def->type, def->ofs);
+ if (!def->initialized)
+ def->initialized = 1;
+}
+
int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata
/*
================
pbool nosave = false;
pbool allocatenew = true;
pbool inlinefunction = false;
- int ispointer;
gofs_t oldglobals;
int arraysize;
+ while (QCC_PR_CheckToken(";"))
+ ;
+
if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
{
if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
QCC_PR_Lex();
}
}
- def = QCC_MakeIntDef(iv);
+ def = QCC_MakeIntConst(iv);
pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
iv++;
QCC_PR_Lex();
}
}
- def = QCC_MakeFloatDef(fv);
+ def = QCC_MakeFloatConst(fv);
pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
fv++;
bits++;
i>>=1;
}
- if (bits != 1)
+ if (bits > 1)
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv);
}
- def = QCC_MakeIntDef(iv);
+ def = QCC_MakeIntConst(iv);
pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
iv*=2;
bits++;
i>>=1;
}
- if (bits != 1)
+ if (bits > 1)
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv);
}
- def = QCC_MakeFloatDef(fv);
+ def = QCC_MakeFloatConst(fv);
pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
fv*=2;
if (QCC_PR_CheckKeyword (keyword_typedef, "typedef"))
{
- type = QCC_PR_ParseType(true);
+ type = QCC_PR_ParseType(true, false);
if (!type)
{
QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens");
}
type->name = QCC_CopyString(pr_token)+strings;
+ type->typedefed = true;
QCC_PR_Lex();
QCC_PR_Expect(";");
return;
if (accglobalsblock == 3)
{
if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
- QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
+ QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
}
QCC_PR_ParseName();
if (accglobalsblock == 3)
{
if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
- QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
+ QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
}
else
if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0, false))
- QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 1, false);
+ QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 0, false);
accglobalsblock = 3;
}
}
break;
}
if (QCC_PR_CheckKeyword(keyword_object, "object"))
- QCC_PR_GetDef(type_entity, name, NULL, true, 1, true);
+ QCC_PR_GetDef(type_entity, name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_string, "string"))
- QCC_PR_GetDef(type_string, name, NULL, true, 1, true);
+ QCC_PR_GetDef(type_string, name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_real, "real"))
{
- def = QCC_PR_GetDef(type_float, name, NULL, true, 1, true);
+ def = QCC_PR_GetDef(type_float, name, NULL, true, 0, true);
if (QCC_PR_CheckToken("="))
{
G_FLOAT(def->ofs) = pr_immediate._float;
}
else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
{
- def = QCC_PR_GetDef(type_vector, name, NULL, true, 1, true);
+ def = QCC_PR_GetDef(type_vector, name, NULL, true, 0, true);
if (QCC_PR_CheckToken("="))
{
QCC_PR_Expect("[");
}
}
else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
- QCC_PR_GetDef(type_function, name, NULL, true, 1, true);
+ QCC_PR_GetDef(type_function, name, NULL, true, 0, true);
else
QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
QCC_PR_Expect (";");
break;
}
if (QCC_PR_CheckKeyword(keyword_object, "object"))
- QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 1, true);
+ QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_string, "string"))
- QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 1, true);
+ QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_real, "real"))
- QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 1, true);
+ QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
- QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 1, true);
+ QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 0, true);
else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
- QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 1, true);
+ QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 0, true);
else
QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
QCC_PR_Expect (";");
break;
}
- type = QCC_PR_ParseType (false);
+ type = QCC_PR_ParseType (false, false);
if (type == NULL) //ignore
return;
QCC_PR_Expect("(");
type = QCC_PR_ParseFunctionTypeReacc(false, type);
QCC_PR_Expect(";");
- if (!stricmp(name, "null"))
- printf("null!\n");
- def = QCC_PR_GetDef (type, name, NULL, true, 1, false);
+ def = QCC_PR_GetDef (type, name, NULL, true, 0, false);
if (autoprototype)
{ //ignore the code and stuff
// if (pr_dumpasm)
// PR_PrintFunction (def);
+ if (numfunctions >= MAX_FUNCTIONS)
+ QCC_Error(ERR_INTERNAL, "Too many function defs");
+
// fill in the dfunction
df = &functions[numfunctions];
numfunctions++;
// QCC_PR_ParseError ("Fields must be global");
do
- {
- if (QCC_PR_CheckToken ("*"))
- {
- ispointer = 1;
- while(QCC_PR_CheckToken ("*"))
- ispointer++;
- name = QCC_PR_ParseName ();
- }
- else if (QCC_PR_CheckToken (";"))
+ {
+ if (QCC_PR_CheckToken (";"))
{
if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct))
{
// }
QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name");
name = NULL;
- ispointer = false;
}
else
{
name = QCC_PR_ParseName ();
- ispointer = false;
}
if (QCC_PR_CheckToken("::") && !classname)
}
else
{
- def = QCC_PR_Expression(TOP_PRIORITY, 0);
- if (!def->constant)
- QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
- else if (def->type->type == ev_integer)
- arraysize = G_INT(def->ofs);
- else if (def->type->type == ev_float)
- {
- arraysize = (int)G_FLOAT(def->ofs);
- if ((float)arraysize != G_FLOAT(def->ofs))
- QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
- }
- else
- QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size must be of int value");
-/* if(pr_token_type == tt_name)
- {
- def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), pr_scope, false, 0);
- if (def && def->arraysize==1)
- {
- if (def->type->type == ev_integer)
- arraysize = G_INT(def->ofs);
- else if (def->type->type == ev_float && (float)(int)G_FLOAT(def->ofs) == G_FLOAT(def->ofs))
- arraysize = (int)G_FLOAT(def->ofs);
- }
- }
- else if (pr_token_type == tt_immediate)
- {
- arraysize = atoi (pr_token);
- QCC_PR_Lex();
- }
-*/ QCC_PR_Expect("]");
+ arraysize = QCC_PR_IntConstExpr();
+ QCC_PR_Expect("]");
}
if (arraysize < 1)
{
QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name);
- arraysize=0; //grrr...
+ arraysize=1; //grrr...
}
}
else
- arraysize = 1;
+ arraysize = 0;
if (QCC_PR_CheckToken("("))
{
oldglobals = numpr_globals;
- if (ispointer)
- {
- parm = type;
- while(ispointer)
- {
- ispointer--;
- parm = QCC_PointerTypeTo(parm);
- }
-
- def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize, !nosave);
- }
- else
- def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
+ def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
if (!def)
QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname);
QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised");
}
- arraysize = def->arraysize;
- d = def; //apply to ALL elements
- while(arraysize--)
+ d = def;
+ while (d != def->deftail)
{
+ d = d->next;
d->initialized = 1; //fake function
G_FUNCTION(d->ofs) = 0;
- d = d->next;
}
continue;
QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);
if (def->initialized == 1)
{
- if (def->type->type == ev_function)
- {
- i = G_FUNCTION(def->ofs);
- df = &functions[i];
- QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
- }
- else
- QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
+// if (def->type->type == ev_function)
+// {
+// i = G_FUNCTION(def->ofs);
+// df = &functions[i];
+// QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
+// }
+// else
+// QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
}
if (autoprototype)
continue;
}
- if (pr_scope)
- {
- d = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
- if (typecmp(def->type, d->type))
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
- if (d->constant)
- {
- for (i = 0; (unsigned)i < def->type->size; i++)
- G_INT(def->ofs+i) = G_INT(d->ofs+i);
- def->constant = !isvar;
- def->initialized = 1;
- continue;
- }
- else if (def->type->size >= 3)
- {
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], d, def, NULL));
- def->constant = false;
- def->initialized = false;
- continue;
- }
- else
- {
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], d, def, NULL));
- def->constant = false;
- def->initialized = false;
- continue;
- }
- }
- else
- if (pr_token_type == tt_name && strcmp(pr_token, "_"))
- {
- unsigned int i;
-
- if (def->arraysize>1)
- QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly braces");
-
- d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
- if (typecmp(def->type, d->type))
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
-
- for (i = 0; i < d->type->size; i++)
- G_INT(def->ofs) = G_INT(d->ofs);
- QCC_PR_Lex();
-
- if (type->type == ev_function)
- {
- def->initialized = 1;
- def->constant = !isvar;
- }
- continue;
- }
-
- else if (type->type == ev_function)
- {
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
- if (QCC_PR_CheckImmediate("0") || QCC_PR_CheckImmediate("0i"))
- {
- def->constant = 0;
- def->initialized = 1; //fake function
- G_FUNCTION(def->ofs) = 0;
- continue;
- }
-
- if (!def->constant && arraysize==1)
- {
- def->constant = 0;
- def->initialized = 1; //fake function
-
- name = QCC_PR_ParseName ();
- d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not previously defined", name);
- G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
- continue;
- }
-
- if (arraysize>1)
- {
- int i;
- def->initialized = 1; //fake function
- QCC_PR_Expect ("{");
- i = 0;
- do
- {
- if (pr_token_type == tt_immediate && (
- (pr_immediate_type == type_integer && pr_immediate._int == 0) ||
- (pr_immediate_type == type_float && pr_immediate._float == 0)))
- {
- QCC_PR_Lex();
- G_FUNCTION(def->ofs+i) = 0;
- }
- else
- {
- name = QCC_PR_ParseName ();
-
- d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined", name);
- else
- {
- if (!d->initialized)
- QCC_PR_ParseWarning(WARN_NOTDEFINED, "initialisation of function arrays must be placed after the body of all functions used (%s)", name);
- G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
- }
- }
-
- i++;
- } while(QCC_PR_CheckToken(","));
-
- arraysize = def->arraysize;
- d = def; //apply to ALL elements
- while(arraysize--)
- {
- d->initialized = 1; //fake function
- d = d->next;
- }
-
- QCC_PR_Expect("}");
- if (i > def->arraysize)
- QCC_PR_ParseError(ERR_TOOMANYINITIALISERS, "Too many initializers");
- continue;
- }
- if (!def->constant)
- QCC_PR_ParseError(0, "Initialised functions must be constant");
-
- def->references++;
- pr_scope = def;
- f = QCC_PR_ParseImmediateStatements (type);
- pr_scope = NULL;
- def->initialized = 1;
- G_FUNCTION(def->ofs) = numfunctions;
- f->def = def;
-// if (pr_dumpasm)
-// PR_PrintFunction (def);
-
- // fill in the dfunction
- df = &functions[numfunctions];
- numfunctions++;
- if (f->builtin)
- df->first_statement = -f->builtin;
- else
- df->first_statement = f->code;
-
- if (f->builtin && opt_function_names)
- optres_function_names += strlen(f->def->name);
- else
- df->s_name = QCC_CopyString (f->def->name);
- df->s_file = s_file2;
- df->numparms = f->def->type->num_parms;
- df->locals = locals_end - locals_start;
- df->parm_start = locals_start;
- for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
- {
- df->parm_size[i] = parm->size;
- }
-
- continue;
- }
-
- else if (type->type == ev_struct)
- {
- int arraypart, partnum;
- QCC_type_t *parttype;
- def->initialized = 1;
- if (isvar)
- def->constant = true;
- else
- def->constant = false;
-// if (constant)
-// QCC_PR_ParseError("const used on a struct isn't useful");
-
- //FIXME: should do this recursivly
- QCC_PR_Expect("{");
- for (arraypart = 0; arraypart < arraysize; arraypart++)
- {
- parttype = type->param;
- QCC_PR_Expect("{");
- for (partnum = 0; partnum < type->num_parms; partnum++)
- {
- switch (parttype->type)
- {
- case ev_float:
- case ev_integer:
- case ev_vector:
- if (pr_token_type == tt_punct)
- {
- if (QCC_PR_CheckToken("{"))
- {
- QCC_PR_Expect("}");
- }
- else
- QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
-
- }
- else if (pr_token_type == tt_immediate)
- {
- if (pr_immediate_type->type == ev_float && parttype->type == ev_integer)
- G_INT(def->ofs + arraypart*type->size + parttype->ofs) = (int)pr_immediate._float;
- else if (pr_immediate_type->type != parttype->type)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
- else
- memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
- }
- else if (pr_token_type == tt_name)
- {
- d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
- else if (d->type->type != parttype->type)
- QCC_PR_ParseError (ERR_WRONGSUBTYPE, "wrong subtype for %s.%s", def->name, parttype->name);
- else if (!d->constant)
- QCC_PR_ParseError(ERR_NOTACONSTANT, "%s isn't a constant\n", pr_token);
-
- memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, qcc_pr_globals + d->ofs, 4*d->type->size);
- }
- else
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
- QCC_PR_Lex ();
-
- break;
- case ev_string:
- if (pr_token_type == tt_punct)
- {
- if (QCC_PR_CheckToken("{"))
- {
- unsigned int i;
- for (i = 0; i < parttype->size; i++)
- {
-/* //the executor defines strings as true c strings, but reads in index from string table.
- //structures can hide these strings.
- d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- d->next = NULL;
- pr.def_tail->next = d;
- pr.def_tail = d;
-
- d->type = parttype;
- d->name = "STRUCTIMMEDIATE";
- d->constant = constant;
- d->initialized = 1;
- d->scope = NULL;
-
- d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
-*/
- G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = QCC_CopyString(pr_immediate_string);
- QCC_PR_Lex ();
-
- if (!QCC_PR_CheckToken(","))
- {
- i++;
- break;
- }
- }
- for (; i < parttype->size; i++)
- {
-/* //the executor defines strings as true c strings, but reads in index from string table.
- //structures can hide these strings.
- d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- d->next = NULL;
- pr.def_tail->next = d;
- pr.def_tail = d;
-
- d->type = parttype;
- d->name = "STRUCTIMMEDIATE";
- d->constant = constant;
- d->initialized = 1;
- d->scope = NULL;
-
- d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
-*/
- G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0;
- }
- QCC_PR_Expect("}");
- }
- else
- QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
- }
- else
- {
-/* //the executor defines strings as true c strings, but reads in index from string table.
- //structures can hide these strings.
- d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- d->next = NULL;
- pr.def_tail->next = d;
- pr.def_tail = d;
-
- d->type = parttype;
- d->name = "STRUCTIMMEDIATE";
- d->constant = constant;
- d->initialized = 1;
- d->scope = NULL;
-
- d->ofs = def->ofs+arraypart*type->size+parttype->ofs;
-*/
- G_INT(def->ofs+arraypart*type->size+parttype->ofs) = QCC_CopyString(pr_immediate_string);
- QCC_PR_Lex ();
- }
- break;
- case ev_function:
- if (pr_token_type == tt_immediate)
- {
- if (pr_immediate._int != 0)
- QCC_PR_ParseError(ERR_NOTFUNCTIONTYPE, "Expected function name or NULL");
- G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = 0;
- QCC_PR_Lex();
- }
- else
- {
- name = QCC_PR_ParseName ();
-
- d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", name);
- else
- G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = G_FUNCTION(d->ofs);
- }
- break;
- default:
- QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type);
- QCC_PR_Lex();
- break;
- }
- if (!QCC_PR_CheckToken(","))
- break;
-
- parttype=parttype->next;
- }
- QCC_PR_Expect("}");
- if (!QCC_PR_CheckToken(","))
- break;
- }
- QCC_PR_Expect("}");
- continue;
- }
-
- else if (type->type == ev_integer) //handle these differently, because they may need conversions
- {
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
-
- def->initialized = 1;
- memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
- QCC_PR_Lex ();
-
- if (pr_immediate_type->type == ev_float)
- G_INT(def->ofs) = (int)pr_immediate._float;
- else if (pr_immediate_type->type != ev_integer)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
- continue;
- }
- else if (type->type == ev_string)
- {
- int dotranslate = 0;
- char buf[64];
- if (!strcmp(pr_token, "_"))
- {
- dotranslate = 1;
- QCC_PR_Lex();
- }
- if(dotranslate)
- QCC_PR_Expect("(");
-
- if (arraysize>=1 && QCC_PR_CheckToken("{"))
- {
- int i;
- for (i = 0; i < arraysize; i++)
- {
- int dotranslate2;
-
- //the executor defines strings as true c strings, but reads in index from string table.
- //structures can hide these strings.
- if (i != 0) //not for the first entry - already a string def for that
- {
- d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- d->next = NULL;
- pr.def_tail->next = d;
- pr.def_tail = d;
-
- d->name = "IMMEDIATE";
- d->type = type_string;
- if (isvar)
- d->constant = false;
- else
- d->constant = true;
- d->initialized = 1;
- d->scope = NULL;
-
- d->ofs = def->ofs+i;
- if (d->ofs >= MAX_REGS)
- QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
- }
-
- if (!strcmp(pr_token, "_"))
- {
- dotranslate2 = 1;
- QCC_PR_Lex();
- }
- if(dotranslate2)
- QCC_PR_Expect("(");
-
- if(dotranslate || dotranslate2)
- {
- sprintf(buf, "dotranslate_%d", ++dotranslate_count);
- d->name = strdup(buf);
- }
-
- (((int *)qcc_pr_globals)[def->ofs+i]) = QCC_CopyString(pr_immediate_string);
- QCC_PR_Lex ();
-
- if(dotranslate2)
- QCC_PR_Expect(")");
-
- if (!QCC_PR_CheckToken(","))
- break;
- }
- QCC_PR_Expect("}");
- }
- else if (arraysize<=1)
- {
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
- def->initialized = 1;
- (((int *)qcc_pr_globals)[def->ofs]) = QCC_CopyString(pr_immediate_string);
- QCC_PR_Lex ();
-
- if(dotranslate)
- {
- sprintf(buf, "dotranslate_%d", ++dotranslate_count);
- def->name = strdup(buf);
- }
-
- if (pr_immediate_type->type == ev_float)
- G_INT(def->ofs) = (int)pr_immediate._float;
- else if (pr_immediate_type->type != ev_string)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
- }
- else
- QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
-
- if(dotranslate)
- QCC_PR_Expect(")");
- continue;
- }
- else if (type->type == ev_float)
- {
- if (arraysize>=1 && QCC_PR_CheckToken("{"))
- {
- int i;
- for (i = 0; i < arraysize; i++)
- {
- if (pr_immediate_type->type != ev_float)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
- (((float *)qcc_pr_globals)[def->ofs+i]) = pr_immediate._float;
- QCC_PR_Lex ();
-
- if (!QCC_PR_CheckToken(","))
- break;
- }
- QCC_PR_Expect("}");
-
- continue;
- }
- else if (arraysize<=1)
- {
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
-
- def->initialized = 1;
-
- if (pr_immediate_type->type != ev_float)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
- if (def->constant && opt_dupconstdefs)
- {
- if (def->ofs == oldglobals)
- {
- if (Hash_GetKey(&floatconstdefstable, *(int*)&pr_immediate._float))
- optres_dupconstdefs++;
- QCC_FreeOffset(def->ofs, def->type->size);
- d = QCC_MakeFloatDef(pr_immediate._float);
- d->references++;
- def->ofs = d->ofs;
- QCC_PR_Lex();
- continue;
- }
- }
-
- (((float *)qcc_pr_globals)[def->ofs]) = pr_immediate._float;
- QCC_PR_Lex ();
-
- continue;
- }
- else
- QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
- }
- else if (type->type == ev_vector)
- {
- if (arraysize>=1 && QCC_PR_CheckToken("{"))
- {
- int i;
- for (i = 0; i < arraysize; i++)
- {
- if (pr_immediate_type->type != ev_vector)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
- (((float *)qcc_pr_globals)[def->ofs+i*3+0]) = pr_immediate.vector[0];
- (((float *)qcc_pr_globals)[def->ofs+i*3+1]) = pr_immediate.vector[1];
- (((float *)qcc_pr_globals)[def->ofs+i*3+2]) = pr_immediate.vector[2];
- QCC_PR_Lex ();
-
- if (!QCC_PR_CheckToken(","))
- break;
- }
- QCC_PR_Expect("}");
-
- continue;
- }
- else if (arraysize<=1)
- {
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
- def->initialized = 1;
-
- if (pr_immediate_type->type != ev_vector)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
- (((float *)qcc_pr_globals)[def->ofs+0]) = pr_immediate.vector[0];
- (((float *)qcc_pr_globals)[def->ofs+1]) = pr_immediate.vector[1];
- (((float *)qcc_pr_globals)[def->ofs+2]) = pr_immediate.vector[2];
- QCC_PR_Lex ();
-
- continue;
- }
- else
- QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
- }
- else if (pr_token_type == tt_name)
- {
-// if (pr_scope)//create a new instance, emit a copy op
-// {
-// QCC_PR_ParseError ("name defined for local : %s", name);
-// }
-// else
- {
- d = QCC_PR_GetDef (NULL, pr_token, pr_scope, false, 0, false);
- if (!d)
- QCC_PR_ParseError (ERR_NOTDEFINED, "initialisation name not defined : %s", pr_token);
- if (!d->constant)
- {
- QCC_PR_ParseWarning (WARN_NOTCONSTANT, "initialisation name not a constant : %s", pr_token);
- QCC_PR_ParsePrintDef(WARN_NOTCONSTANT, d);
- }
- memcpy (def, d, sizeof(*d));
- def->name = name;
- def->initialized = true;
- }
- }
- else if (pr_token_type != tt_immediate)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "not an immediate for %s - %s", name, pr_token);
- else if (pr_immediate_type->type != type->type)
- QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s - %s", name, pr_token);
- else
- memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
-
- if (isvar)
- def->constant = false;
- else
- def->constant = true;
- def->initialized = true;
- QCC_PR_Lex ();
+ QCC_PR_ParseInitializerDef(def, isvar, isconstant);
}
else
{
def->constant = isconstant;
}
-
+ d = def;
+ while (d != def->deftail)
+ {
+ d = d->next;
+ d->constant = def->constant;
+ d->initialized = def->initialized;
+ }
} while (QCC_PR_CheckToken (","));
if (type->type == ev_function)
int opr_source_line;
char *ocompilingfile;
struct qcc_includechunk_s *oldcurrentchunk;
- extern struct qcc_includechunk_s *currentchunk;
ocompilingfile = compilingfile;
os_file = s_file;