From 0ac9b88343ee0e38d2e326c25d2796bb561efdce Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 11 Jun 2013 02:06:06 +0000 Subject: [PATCH] Misc fixes and tweaks. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4390 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/qcc.h | 2 +- engine/qclib/qcc_pr_comp.c | 168 +++++++++++++++++++------------------ engine/qclib/qcc_pr_lex.c | 40 ++++++--- engine/qclib/qccmain.c | 30 ++++--- 4 files changed, 133 insertions(+), 107 deletions(-) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index d1a134df..2700c92e 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -839,7 +839,7 @@ extern QCC_def_t def_ret, def_parms[MAX_PARMS]; void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname); void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname); -void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname); +void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype); void PostCompile(void); pbool PreCompile(void); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 38c40980..368e2ad5 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -455,12 +455,12 @@ QCC_opcode_t pr_opcodes[] = -{7, "*", "MUL_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, +{7, "*", "MUL_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_float}, {7, "*", "MUL_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float}, {7, "*", "MUL_VI", 5, ASSOC_LEFT, &type_vector, &type_integer, &type_vector}, {7, "*", "MUL_IV", 5, ASSOC_LEFT, &type_integer, &type_vector, &type_vector}, -{7, "/", "DIV_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, +{7, "/", "DIV_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_float}, {7, "/", "DIV_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float}, {7, "&", "BITAND_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, @@ -1535,13 +1535,13 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size) sprintf(message, "\"%.1020s\"", &strings[((int *)qcc_pr_globals)[var->ofs]]); return message; case ev_integer: - sprintf(message, "%i", ((int *)qcc_pr_globals)[var->ofs]); + sprintf(message, "%ii", ((int *)qcc_pr_globals)[var->ofs]); return message; case ev_float: - sprintf(message, "%f", qcc_pr_globals[var->ofs]); + sprintf(message, "%g", qcc_pr_globals[var->ofs]); return message; case ev_vector: - sprintf(message, "'%f %f %f'", qcc_pr_globals[var->ofs], qcc_pr_globals[var->ofs+1], qcc_pr_globals[var->ofs+2]); + sprintf(message, "'%g %g %g'", qcc_pr_globals[var->ofs], qcc_pr_globals[var->ofs+1], qcc_pr_globals[var->ofs+2]); return message; default: sprintf(message, "IMMEDIATE"); @@ -1696,6 +1696,12 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_MUL_I: optres_constantarithmatic++; return QCC_MakeIntConst(G_INT(var_a->ofs) * G_INT(var_b->ofs)); + case OP_MUL_IF: + optres_constantarithmatic++; + return QCC_MakeFloatConst(G_INT(var_a->ofs) * G_FLOAT(var_b->ofs)); + case OP_MUL_FI: + optres_constantarithmatic++; + return QCC_MakeIntConst(G_FLOAT(var_a->ofs) * G_INT(var_b->ofs)); case OP_DIV_I: optres_constantarithmatic++; if (G_INT(var_b->ofs) == 0) @@ -1719,6 +1725,13 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ optres_constantarithmatic++; return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_INT(var_b->ofs)); + case OP_SUB_IF: + optres_constantarithmatic++; + return QCC_MakeFloatConst(G_INT(var_a->ofs) - G_FLOAT(var_b->ofs)); + case OP_SUB_FI: + optres_constantarithmatic++; + return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) - G_INT(var_b->ofs)); + case OP_AND_F: optres_constantarithmatic++; return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs)); @@ -2271,13 +2284,14 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ var_a = var_c; var_c = var_a; break; - case OP_ADDSTORE_IF: - op = &pr_opcodes[OP_ADD_IF]; - var_c = var_b; - var_b = var_a; - var_a = var_c; - var_c = var_a; - break; +// case OP_ADDSTORE_IF: +// fixme: result is a float but needs to be an int +// op = &pr_opcodes[OP_ADD_IF]; +// var_c = var_b; +// var_b = var_a; +// var_a = var_c; +// var_c = var_a; +// break; case OP_SUBSTORE_F: op = &pr_opcodes[OP_SUB_F]; @@ -2293,13 +2307,14 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ var_a = var_c; var_c = var_a; break; - case OP_SUBSTORE_IF: - op = &pr_opcodes[OP_SUB_IF]; - var_c = var_b; - var_b = var_a; - var_a = var_c; - var_c = var_a; - break; +// case OP_SUBSTORE_IF: +// fixme: result is a float but needs to be an int +// op = &pr_opcodes[OP_SUB_IF]; +// var_c = var_b; +// var_b = var_a; +// var_a = var_c; +// var_c = var_a; +// break; case OP_SUBSTORE_I: op = &pr_opcodes[OP_SUB_I]; var_c = var_b; @@ -2333,13 +2348,14 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ var_a = var_c; var_c = var_a; break; - case OP_DIVSTORE_IF: - op = &pr_opcodes[OP_DIV_IF]; - var_c = var_b; - var_b = var_a; - var_a = var_c; - var_c = var_a; - break; +// case OP_DIVSTORE_IF: +// fixme: result is a float, but needs to be an int +// op = &pr_opcodes[OP_DIV_IF]; +// var_c = var_b; +// var_b = var_a; +// var_a = var_c; +// var_c = var_a; +// break; case OP_DIVSTORE_I: op = &pr_opcodes[OP_DIV_I]; var_c = var_b; @@ -2355,13 +2371,14 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ var_a = var_c; var_c = var_a; break; - case OP_MULSTORE_IF: - op = &pr_opcodes[OP_MUL_IF]; - var_c = var_b; - var_b = var_a; - var_a = var_c; - var_c = var_a; - break; +// case OP_MULSTORE_IF: +// fixme: result is a float, but needs to be an int +// op = &pr_opcodes[OP_MUL_IF]; +// var_c = var_b; +// var_b = var_a; +// var_a = var_c; +// var_c = var_a; +// break; case OP_MULSTORE_FI: op = &pr_opcodes[OP_MUL_FI]; var_c = var_b; @@ -3058,41 +3075,31 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *newself, QCC_def_t *func, QCC oself = NULL; d = NULL; - if (strchr(func->name, ':') && func->temp) + if (newself) { - //the function might be: - //parentclass::func(); - //global.func(); - //local.func(); - if (func->temp && newself) + //we're entering OO code with a different self. make sure self is preserved. + //eg: other.touch(self) + + self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); + if (newself->ofs != self->ofs) { - //we're entering OO code with a different self. make sure self is preserved. - //eg: other.touch(self) + oself = QCC_GetTemp(type_entity); + //oself = self + QCC_PR_SimpleStatement(OP_STORE_ENT, self->ofs, oself->ofs, 0, false); + //self = other + QCC_PR_SimpleStatement(OP_STORE_ENT, newself->ofs, self->ofs, 0, false); - self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); - if (newself->ofs != self->ofs) + //if the args refered to self, update them to refer to oself instead + //(as self is now set to 'other') + for (i = 0; i < argcount; i++) { - oself = QCC_GetTemp(type_entity); - //oself = self - QCC_PR_SimpleStatement(OP_STORE_ENT, self->ofs, oself->ofs, 0, false); - //self = other - QCC_PR_SimpleStatement(OP_STORE_ENT, newself->ofs, self->ofs, 0, false); - - //if the args refered to self, update them to refer to oself instead - //(as self is now set to 'other') - for (i = 0; i < argcount; i++) + if (arglist[i]->ofs == self->ofs) { - if (arglist[i]->ofs == self->ofs) - { - arglist[i] = oself; - } + arglist[i] = oself; } } } - else if (pr_classtype) - { - QCC_PR_ParseWarning(0, "Class-specific call from non-class function\n"); - } + QCC_FreeTemp(newself); } // write the arguments (except for first two if hexenc) @@ -4264,6 +4271,14 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas, int *basictypefield) f = QCC_MemberInParentClass(clas->params[p].paramname, clas->parentclass); if (f) { + if (f->type->type != ev_field || typecmp(f->type->aux_type, mt)) + { + char ct[256]; + char pt[256]; + TypeName(f->type->aux_type, pt, sizeof(pt)); + TypeName(mt, ct, sizeof(ct)); + QCC_PR_Warning(0, NULL, 0, "type mismatch on inheritance of %s::%s. %s vs %s", clas->name, clas->params[p].paramname, ct, pt); + } if (!m) { basictypefield[mt->type] += 1; @@ -4373,9 +4388,9 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_ } //take all functions in the type, and parent types, and make sure the links all work properly. -void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) +void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) { - QCC_type_t *basetype, *parenttype; + QCC_type_t *parenttype; QCC_dfunction_t *df; @@ -4387,10 +4402,6 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) // int func; - basetype = QCC_TypeForName(tname); - 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"); @@ -4407,7 +4418,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) numfunctions++; df->s_file = scope->s_file; - df->s_name = 0; + df->s_name = QCC_CopyString(scope->name); df->first_statement = numstatements; df->parm_size[0] = 1; df->numparms = 0; @@ -4523,27 +4534,22 @@ static QCC_def_t *QCC_PR_ExpandField(QCC_def_t *ent, QCC_def_t *field) //FIXME: maybe we should have a thiscall attribute instead? need to relax the check in QCC_PR_ParseField to any entity type if (ent->type->parentclass && QCC_PR_CheckToken("(")) { + QCC_def_t *func; QCC_def_t *nthis = ent; + nthis->references++; + field->references++; if (ent->temp) { //we need to make sure that d does not get clobbered by the load_fld. //note that this is kinda inefficient as we'll be copying this value into self later on anyway. QCC_def_t *t = QCC_GetTemp(type_entity); - nthis = QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], nthis, t, NULL); + nthis = QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], nthis, t, NULL); QCC_UnFreeTemp(nthis); } - r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], ent, field, NULL); - tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - memset (tmp, 0, sizeof(QCC_def_t)); - tmp->type = field->type->aux_type; - tmp->ofs = r->ofs; - tmp->temp = r->temp; - tmp->constant = false; - tmp->name = r->name; - r = tmp; - + func = QCC_GetTemp(field->type->aux_type); + QCC_PR_SimpleStatement(OP_LOAD_FNC, nthis->ofs, field->ofs, func->ofs, false); qcc_usefulstatement=true; - r = QCC_PR_ParseFunctionCall(nthis, r); + r = QCC_PR_ParseFunctionCall(nthis, func); r = QCC_PR_ParseArrayPointer(r, true); } else @@ -9149,7 +9155,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); else sprintf(newname, "%s%s", parttype->name, array); - ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false); + 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. @@ -9170,7 +9176,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, 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, false); + ftype = QCC_PR_NewType("FIELD_TYPE", ev_field, false); ftype->aux_type = parttype; def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); def->initialized = true; diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index a58f7bd6..b97ed8db 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -3735,7 +3735,7 @@ QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto) { QCC_type_t *ptype; char name[128]; - sprintf(name, "FIELD TYPE(%s)", pointsto->name); + sprintf(name, "FIELD_TYPE(%s)", pointsto->name); ptype = QCC_PR_NewType(name, ev_field, false); ptype->aux_type = pointsto; ptype->size = ptype->aux_type->size; @@ -3761,14 +3761,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges) { - newt = QCC_PR_NewType("FIELD TYPE", ev_field, false); + newt = QCC_PR_NewType("FIELD_TYPE", ev_field, false); newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; newt = QCC_PR_FindType (newt); - type = QCC_PR_NewType("FIELD TYPE", ev_field, false); + type = QCC_PR_NewType("FIELD_TYPE", ev_field, false); type->aux_type = newt; type->size = type->aux_type->size; @@ -3779,7 +3779,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) } if (QCC_PR_CheckToken (".")) { - newt = QCC_PR_NewType("FIELD TYPE", ev_field, false); + newt = QCC_PR_NewType("FIELD_TYPE", ev_field, false); newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; @@ -3881,6 +3881,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) isvirt = true; newparm = QCC_PR_ParseType(false, false); + if (!newparm) + QCC_PR_ParseError(ERR_INTERNAL, "In class %s, expected type, found %s", classname, pr_token); + if (newparm->type == ev_struct || newparm->type == ev_union) //we wouldn't be able to handle it. QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname); @@ -3953,34 +3956,37 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) if (!isvirt && !isstatic) { + QCC_def_t *fdef; QCC_type_t *pc; unsigned int i; isstatic = true; //assume static if its initialised inside the function. + for (pc = newt->parentclass; pc; pc = pc->parentclass) { for (i = 0; i < pc->num_parms; i++) { if (!strcmp(pc->params[i].paramname, parmname)) { - QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s::%s is virtual inside parent class %s. Did you forget the 'virtual' keyword?", newt->name, parmname, pc->name); + QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s::%s is virtual inside parent class '%s'. Did you forget the 'virtual' keyword?", newt->name, parmname, pc->name); break; } } if (i < pc->num_parms) break; } + if (!pc) + { + fdef = QCC_PR_GetDef(NULL, parmname, NULL, false, 0, GDF_CONST); + if (fdef && fdef->type->type == ev_field) + { + QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s::%s is virtual inside parent class 'entity'. Did you forget the 'virtual' keyword?", newt->name, parmname); + } + } } } QCC_PR_Expect(";"); - if (!strcmp(parmname, classname)) - { - //if there's a constructor, make sure the spawnfunc_ function is defined so that its available to maps. - sprintf(membername, "spawnfunc_%s", classname); - QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST); - } - //static members are technically funny-named globals, and do not generate fields. if (isstatic || (newparm->type == ev_function && !arraysize)) { @@ -4036,6 +4042,16 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) memcpy(newt->params, parms, sizeof(*type->params) * numparms); free(parms); + + { + QCC_def_t *d; + //if there's a constructor, make sure the spawnfunc_ function is defined so that its available to maps. + sprintf(membername, "spawnfunc_%s", classname); + d = QCC_PR_GetDef(type_function, membername, NULL, true, 0, GDF_CONST); + d->timescalled++; + d->references++; + } + QCC_PR_Expect(";"); return NULL; } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index e69262f3..29a34fb2 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -837,7 +837,7 @@ pbool QCC_WriteData (int crc) { int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED; pr_scope = def->scope; - if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references", def->name)) + if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references.", def->name)) { if (!warnedunref) { @@ -1820,6 +1820,7 @@ Returns false if errors were detected. int QCC_PR_FinishCompilation (void) { QCC_def_t *d; + QCC_type_t *t; int errors; errors = false; @@ -1837,25 +1838,28 @@ int QCC_PR_FinishCompilation (void) { QCC_PR_EmitArrayGetFunction(d, d->name+9); pr_scope = NULL; + continue; } - else if (!strncmp(d->name, "ArraySet*", 9)) + if (!strncmp(d->name, "ArraySet*", 9)) { QCC_PR_EmitArraySetFunction(d, d->name+9); pr_scope = NULL; + continue; } - else if (!strncmp(d->name, "spawnfunc_", 10)) + if (!strncmp(d->name, "spawnfunc_", 10)) { - QCC_PR_EmitClassFromFunction(d, d->name+10); - pr_scope = NULL; + t = QCC_TypeForName(d->name+10); + if (t) + { + QCC_PR_EmitClassFromFunction(d, t); + pr_scope = NULL; + continue; + } } - else - { - QCC_PR_Warning(ERR_NOFUNC, strings + d->s_file, d->s_line, "function %s has no body",d->name); - QCC_PR_ParsePrintDef(ERR_NOFUNC, d); - bodylessfuncs = true; - errors = true; - } -// errors = true; + QCC_PR_Warning(ERR_NOFUNC, strings + d->s_file, d->s_line, "function %s has no body",d->name); + QCC_PR_ParsePrintDef(ERR_NOFUNC, d); + bodylessfuncs = true; + errors = true; } else if (d->initialized==2) bodylessfuncs = true;