diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index f11df8c71..06ad5cb2e 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -379,6 +379,16 @@ enum qcop_e { OP_BITCLR_F, OP_BITCLR_I, + OP_ADD_PF, + OP_ADD_FP, + OP_ADD_PI, + OP_ADD_IP, + + OP_SUB_PF, + OP_SUB_PI, + + OP_SUB_PP, + OP_NUMOPS }; diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 4a959d645..08e31cdd6 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -365,6 +365,7 @@ typedef struct QCC_def_s pbool isstatic:1; pbool subscoped_away:1; pbool followptr:1; + pbool strip:1; temp_t *temp; } QCC_def_t; @@ -377,6 +378,7 @@ typedef struct REF_POINTER,//*(pointerdef+wordindex) - maths... REF_FIELD, //(entity.field) - reading is a single load, writing requires address+storep REF_STRING, //"hello"[1]=='e' - special opcodes, or str2chr builtin, or something + REF_NONVIRTUAL //(global.ofs) - identical to global except for function calls, where index can be used to provide the 'newself' for the call. } type; QCC_def_t *base; @@ -833,6 +835,7 @@ void QCC_PR_NewLine (pbool incomment); #define GDF_SAVED 1 #define GDF_STATIC 2 #define GDF_CONST 4 +#define GDF_STRIP 8 //always stripped, regardless of optimisations. used for class member fields QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, unsigned int flags); char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 00393f122..2a726ec49 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -594,6 +594,14 @@ QCC_opcode_t pr_opcodes[] = {7, "&~", "BITCLR_F", 6, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "&~", "BITCLR_I", 6, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "+", "ADD_PF", 6, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer}, + {7, "+", "ADD_FP", 6, ASSOC_LEFT, &type_float, &type_pointer, &type_pointer}, + {7, "+", "ADD_PI", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, + {7, "+", "ADD_IP", 6, ASSOC_LEFT, &type_integer, &type_pointer, &type_pointer}, + {7, "-", "SUB_PF", 6, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer}, + {7, "-", "SUB_PI", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, + {7, "-", "SUB_PP", 6, ASSOC_LEFT, &type_pointer, &type_pointer, &type_integer}, + {0, NULL} }; @@ -854,6 +862,10 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_ADD_FI], &pr_opcodes[OP_ADD_IF], &pr_opcodes[OP_ADD_SF], + &pr_opcodes[OP_ADD_PF], + &pr_opcodes[OP_ADD_FP], + &pr_opcodes[OP_ADD_PI], + &pr_opcodes[OP_ADD_IP], &pr_opcodes[OP_SUB_F], &pr_opcodes[OP_SUB_V], @@ -861,6 +873,9 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_SUB_FI], &pr_opcodes[OP_SUB_IF], &pr_opcodes[OP_SUB_S], + &pr_opcodes[OP_SUB_PF], + &pr_opcodes[OP_SUB_PI], + &pr_opcodes[OP_SUB_PP], NULL }, { //5 @@ -2456,6 +2471,42 @@ QCC_def_t *QCC_PR_StatementFlags (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t // QCC_PR_ParseWarning(0, "OP_LOADA_STRUCT: cannot emulate"); break; + case OP_ADD_PF: + case OP_ADD_FP: + case OP_ADD_PI: + case OP_ADD_IP: + numstatements--; + var_c = (op == &pr_opcodes[OP_ADD_PF] || op == &pr_opcodes[OP_ADD_PI])?var_a:var_b; + var_b = (op == &pr_opcodes[OP_ADD_PF] || op == &pr_opcodes[OP_ADD_PI])?var_b:var_a; + QCC_UnFreeTemp(var_c); + if (op == &pr_opcodes[OP_ADD_FP] || op == &pr_opcodes[OP_ADD_PF]) + var_b = QCC_SupplyConversion(var_b, ev_integer, true); //FIXME: this should be an unconditional float->int conversion + var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_I], var_b, QCC_MakeIntConst(var_c->type->size), NULL, 0); + QCC_FreeTemp(var_c); + return QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], var_c, var_b, NULL, 0); + case OP_SUB_PF: + case OP_SUB_PI: + numstatements--; + var_c = var_a; + var_b = var_b; + QCC_UnFreeTemp(var_c); + if (op == &pr_opcodes[OP_SUB_PF]) + var_b = QCC_SupplyConversion(var_b, ev_integer, true); //FIXME: this should be an unconditional float->int conversion + //fixme: word size + var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_I], var_b, QCC_MakeIntConst(var_c->type->size*4), NULL, 0); + QCC_FreeTemp(var_c); + return QCC_PR_StatementFlags(&pr_opcodes[OP_SUB_I], var_c, var_b, NULL, 0); + case OP_SUB_PP: + numstatements--; + if (typecmp(var_a->type, var_b->type)) + QCC_PR_ParseError(0, "incompatible pointer types"); + //determine byte offset + var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_SUB_I], var_a, var_b, NULL, 0); + //determine divisor (fixme: word size) + var_b = QCC_MakeIntConst(var_c->type->size*4); + //divide the result + return QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_I], var_c, var_b, NULL, 0); + case OP_ADD_I: { QCC_def_t *arg[2] = {var_a, var_b}; @@ -3257,7 +3308,7 @@ QCC_ref_t *QCC_PR_GenerateAddressOf(QCC_ref_t *retbuf, QCC_ref_t *operand) REF_GLOBAL, QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], operand->base, operand->index, NULL), NULL, - (operand->index->type->type == ev_field)?operand->index->type->aux_type:type_variant, + QCC_PR_PointerType((operand->index->type->type == ev_field)?operand->index->type->aux_type:type_variant), true); } if (operand->type == REF_GLOBAL || operand->type == REF_ARRAY) @@ -3698,6 +3749,11 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou newself = funcref->base; func = QCC_RefToDef(funcref, false); } + else if (funcref->type == REF_NONVIRTUAL) + { + newself = funcref->index; + func = QCC_RefToDef(funcref, false); + } else { newself = NULL; @@ -5085,6 +5141,14 @@ static QCC_ref_t *QCC_PR_ParseField(QCC_ref_t *refbuf, QCC_ref_t *lhs) } else { + if (field->type == REF_GLOBAL && strstr(field->base->name, "::")) + { + QCC_def_t *theent = QCC_RefToDef(lhs, true); + *refbuf = *field; + refbuf->type = REF_NONVIRTUAL; + refbuf->index = theent; + return refbuf; + } if (t->parentclass) QCC_PR_ParseError(ERR_INTERNAL, "%s is not a field of class %s", QCC_RefToDef(field, false)->name, t->name); else @@ -5479,10 +5543,19 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo { //try getting a member. QCC_type_t *type; type = assumeclass; - while(!d && type) + while(type) { + //look for virtual things sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + if (d) + break; + + //look for non-virtual things (functions: after virtual stuff, because this will find the actual function def too) + sprintf(membername, "%s::%s", type->name, name); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + if (d) + break; type = type->parentclass; } @@ -6340,11 +6413,14 @@ QCC_def_t *QCC_RefToDef(QCC_ref_t *ref, pbool freetemps) ref->base = origv; ref->index = NULL; ref->readonly = true; + return origv; } switch(ref->type) { + case REF_NONVIRTUAL: + break; case REF_GLOBAL: case REF_ARRAY: if (ref->index) @@ -6456,7 +6532,7 @@ QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pb { QCC_def_t *dd; // QCC_PR_ParseWarning(0, "FIXME: trying to do references: assignments to arrays with const offset not supported.\n"); - + case REF_NONVIRTUAL: dest->base->references++; dd = (void *)qccHunkAlloc (sizeof(QCC_def_t)); memset (dd, 0, sizeof(QCC_def_t)); @@ -6650,6 +6726,7 @@ QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_def_t *lhs, QCC_def_t *rhs, QCC_opcode_t * if (op->associative!=ASSOC_LEFT) {//assignment +#if 0 if (op->type_a == &type_pointer) //ent var { /*FIXME: I don't like this code*/ @@ -6663,6 +6740,7 @@ QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_def_t *lhs, QCC_def_t *rhs, QCC_opcode_t * c = QCC_canConv(rhs, (*op->type_c)->type); } else +#endif { c=QCC_canConv(rhs, (*op->type_b)->type); if (type_a != (*op->type_a)->type) //in this case, a is the final assigned value @@ -9821,6 +9899,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a def->saved = !!(flags & GDF_SAVED); def->constant = !!(flags & GDF_CONST); def->isstatic = !!(flags & GDF_STATIC); + def->strip = !!(flags & GDF_STRIP); def->ofs = ofs + type->size*a; if (!first) diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 888fbfcf4..0a4f56316 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -4379,13 +4379,13 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) QCC_PR_Expect(";"); - //static members are technically funny-named globals, and do not generate fields. - if (isstatic || (newparm->type == ev_function && !arraysize)) + //static members are technically just funny-named globals, and do not generate fields. + if (isnonvirt || isstatic || (newparm->type == ev_function && !arraysize)) { sprintf(membername, "%s::%s", classname, parmname); QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST); - if (isstatic) + if (isnonvirt || isstatic) continue; } @@ -4471,7 +4471,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) //actually, that seems pointless. sprintf(membername, "%s::"MEMBERFIELDNAME, classname, parmname); // printf("define %s -> %s\n", membername, d->name); - d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d->ofs, true, GDF_CONST); + d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d->ofs, true, GDF_CONST|GDF_STRIP); d->references++; //always referenced, so you can inherit safely. } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 28de640d4..720736f4e 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -875,6 +875,9 @@ pbool QCC_WriteData (int crc) } } + if (def->strip) + continue; + if (def->type->type == ev_function) { if (opt_function_names && def->initialized && functions[G_FUNCTION(def->ofs)].first_statement<0) @@ -1482,49 +1485,42 @@ strofs = (strofs+3)&~3; printf("Compile finished: %s\n", destfile); - if (!debugtarget) + if (statement_linenums) { - if (opt_filenames) + unsigned int lnotype = *(unsigned int*)"LNOF"; + unsigned int version = 1; + pbool gz = false; + while(1) { - printf("Not writing linenumbers file due to conflicting optimisation (try -Ono-f)\n"); - } - else - { - unsigned int lnotype = *(unsigned int*)"LNOF"; - unsigned int version = 1; - pbool gz = false; - while(1) - { - char *ext; - ext = strrchr(destfile, '.'); - if (strchr(ext, '/') || strchr(ext, '\\')) - break; - if (!stricmp(ext, ".gz")) - { - *ext = 0; - gz = true; - continue; - } - *ext = 0; + char *ext; + ext = strrchr(destfile, '.'); + if (strchr(ext, '/') || strchr(ext, '\\')) break; - } - if (strlen(destfile) < sizeof(destfile)-(4+3)) + if (!stricmp(ext, ".gz")) { - strcat(destfile, ".lno"); - if (gz) - strcat(destfile, ".gz"); - if (verbose) - printf("Writing %s for debugging\n", destfile); - h = SafeOpenWrite (destfile, 2*1024*1024); - SafeWrite (h, &lnotype, sizeof(int)); - SafeWrite (h, &version, sizeof(int)); - SafeWrite (h, &numglobaldefs, sizeof(int)); - SafeWrite (h, &numpr_globals, sizeof(int)); - SafeWrite (h, &numfielddefs, sizeof(int)); - SafeWrite (h, &numstatements, sizeof(int)); - SafeWrite (h, statement_linenums, numstatements*sizeof(int)); - SafeClose (h); + *ext = 0; + gz = true; + continue; } + *ext = 0; + break; + } + if (strlen(destfile) < sizeof(destfile)-(4+3)) + { + strcat(destfile, ".lno"); + if (gz) + strcat(destfile, ".gz"); + if (verbose) + printf("Writing %s for debugging\n", destfile); + h = SafeOpenWrite (destfile, 2*1024*1024); + SafeWrite (h, &lnotype, sizeof(int)); + SafeWrite (h, &version, sizeof(int)); + SafeWrite (h, &numglobaldefs, sizeof(int)); + SafeWrite (h, &numpr_globals, sizeof(int)); + SafeWrite (h, &numfielddefs, sizeof(int)); + SafeWrite (h, &numstatements, sizeof(int)); + SafeWrite (h, statement_linenums, numstatements*sizeof(int)); + SafeClose (h); } }