From e2ef3f2b659cf0972b502394c6062ffbdc98fc23 Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 4 Nov 2004 04:19:10 +0000 Subject: [PATCH] Revised array usage, partly added pointers, added a couple of warnings (preventing crashes...) and fixed two array bugs that appear with non-vector arrays with > 15 elements. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@393 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/pr_comp.h | 5 + engine/qclib/qcc.h | 8 +- engine/qclib/qcc_pr_comp.c | 278 +++++++++++++++++++++++++------------ engine/qclib/qcc_pr_lex.c | 76 ++++++++-- engine/qclib/qccguistuff.c | 2 +- engine/qclib/qccmain.c | 24 ++-- 6 files changed, 285 insertions(+), 108 deletions(-) diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index 98e6a45db..e5a8117c1 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -285,6 +285,8 @@ enum { OP_OR_FI, OP_NE_IF, OP_NE_FI, + +//erm... FTEQCC doesn't make use of these... These are for DP. OP_GSTOREP_I, OP_GSTOREP_F, //190 OP_GSTOREP_ENT, @@ -301,6 +303,9 @@ enum { OP_GLOAD_FNC, OP_BOUNDCHECK, +//back to ones that we do use. + OP_STOREP_P, + OP_NUMOPS }; diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 3c9257fd5..47cac0293 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -606,6 +606,7 @@ enum { ERR_BADIMMEDIATETYPE, ERR_NOOUTPUT, ERR_NOTAFUNCTION, + ERR_FUNCTIONWITHVARGS, ERR_BADHEX, ERR_UNKNOWNPUCTUATION, ERR_EXPECTED, @@ -660,6 +661,7 @@ enum { ERR_WRONGSUBTYPE, ERR_EOF, ERR_NOPRECOMPILERIF, + ERR_NOENDIF, ERR_HASHERROR, ERR_NOTATYPE, ERR_TOOMANYPACKFILES, @@ -738,9 +740,9 @@ extern QCC_string_t s_file; // filename for function definition extern QCC_def_t def_ret, def_parms[MAX_PARMS]; -func_t QCC_PR_EmitArrayGetFunction(char *arrayname); -func_t QCC_PR_EmitArraySetFunction(char *arrayname); -int QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname); +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); //============================================================================= diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index c5ab9befd..7c6514c06 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -88,6 +88,7 @@ int optres_test2; QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable); 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); void QCC_PR_ParseState (void); pbool simplestore; @@ -348,7 +349,7 @@ QCC_opcode_t pr_opcodes[] = {7, "<<", "LSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, //var, offset return - {7, "", "GET_POINTER", -1, ASSOC_LEFT, &type_void, &type_integer, &type_pointer}, + {7, "", "GET_POINTER", -1, ASSOC_LEFT, &type_float, &type_integer, &type_pointer}, {7, "", "ARRAY_OFS", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, {7, "=", "LOADA_F", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float}, @@ -359,7 +360,7 @@ QCC_opcode_t pr_opcodes[] = {7, "=", "LOADA_FNC", 6, ASSOC_LEFT, &type_function, &type_integer, &type_function}, {7, "=", "LOADA_I", 6, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "=", "STORE_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer}, + {7, "=", "STORE_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, {7, ".", "INDIRECT_P", 1, ASSOC_LEFT, &type_entity, &type_field, &type_pointer}, {7, "=", "LOADP_F", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_float}, @@ -425,42 +426,28 @@ QCC_opcode_t pr_opcodes[] = -/* -{7, "!=", "GSTOREP_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_I, -{7, "!=", "GSTORE_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_F, //190 -{7, "!=", "GSTORE_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_ENT, -{7, "!=", "GSTORE_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_FLD, // integers -{7, "!=", "GSTORE_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_S, -{7, "!=", "GSTORE_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_FNC, // pointers -{7, "!=", "GSTORE_V", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GSTOREP_V, -{7, "!=", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GADDRESS, +{7, "<>", "GSTOREP_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTORE_PFNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_V", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "!=", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_I, -{7, "!=", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_F, -{7, "!=", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_FLD, -{7, "!=", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_ENT, //200 -{7, "!=", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_S, -{7, "!=", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_GLOAD_FNC, +{7, "<>", "GADDRESS", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, + +{7, "<>", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{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, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, - {7, "!=", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, - OP_BOUNDCHECK, -*/ - {0, NULL} }; @@ -514,6 +501,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &pr_opcodes[OP_LOAD_FLD], &pr_opcodes[OP_LOAD_FNC], &pr_opcodes[OP_LOAD_I], + &pr_opcodes[OP_LOAD_P], &pr_opcodes[OP_ADDRESS], NULL }, { //2 @@ -607,6 +595,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &pr_opcodes[OP_STORE_I], &pr_opcodes[OP_STORE_IF], &pr_opcodes[OP_STORE_FI], + &pr_opcodes[OP_STORE_P], &pr_opcodes[OP_STOREP_F], &pr_opcodes[OP_STOREP_V], @@ -617,6 +606,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &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_DIVSTOREP_F], @@ -950,6 +940,7 @@ static void QCC_FreeTemps(void) if (t->used && !pr_error_count) //don't print this after an error jump out. { QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used\n"); + t->used = false; } t = t->next; } @@ -1678,7 +1669,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; break; default: - QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", op->name, op->opname); + QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname); break; } } @@ -2489,6 +2480,9 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could case ev_string: e = QCC_PR_Statement(pr_opcodes+OP_LOAD_S, oself, e, NULL); break; + case ev_integer: + e = QCC_PR_Statement(pr_opcodes+OP_LOAD_I, oself, e, NULL); + break; case ev_float: e = QCC_PR_Statement(pr_opcodes+OP_LOAD_F, oself, e, NULL); break; @@ -2959,7 +2953,7 @@ 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. -int QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) +void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) { QCC_type_t *basetype; @@ -2987,6 +2981,8 @@ int QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) df->numparms = 1; df->parm_start = numpr_globals; + G_FUNCTION(scope->ofs) = df - functions; + //locals here... ed = QCC_PR_GetDef(type_entity, "ent", NULL, true, 1); @@ -3025,9 +3021,6 @@ int QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) locals_end = numpr_globals + basetype->size; df->locals = locals_end - df->parm_start; - - //basetype - return df - functions; } /* ============ @@ -3118,6 +3111,7 @@ reloop: numstatements--; //remove the last statement nd = QCC_PR_Expression (TOP_PRIORITY); + QCC_PR_Expect("]"); if (d->type->size != 1) //we need to multiply it to find the offset. { @@ -3157,6 +3151,7 @@ reloop: else { ao = QCC_PR_Expression (TOP_PRIORITY); + QCC_PR_Expect("]"); if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1) //we need to multiply it to find the offset. { @@ -3223,8 +3218,7 @@ reloop: { if (qcc_targetformat == QCF_HEXEN2) { //hexen2 style retrieval, mixed with q1 style assignments... - QCC_PR_Expect("]"); - if (QCC_PR_Check("=")) + if (QCC_PR_Check("=")) //(hideous concept) { QCC_dstatement_t *st; QCC_def_t *funcretr; @@ -3239,8 +3233,10 @@ reloop: QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); QCC_PR_Statement (&pr_opcodes[OP_CALL2H], funcretr, 0, &st); - st->a = d->ofs; + st->a = ao->ofs; st->b = nd->ofs; + QCC_FreeTemp(ao); + QCC_FreeTemp(nd); qcc_usefulstatement = true; nd = &def_ret; @@ -3276,6 +3272,8 @@ reloop: nd = NULL; break; } + QCC_FreeTemp(d); + QCC_FreeTemp(ao); d=nd; d->type = newtype; @@ -3291,9 +3289,8 @@ reloop: if (def_ret.temp->used && ao != &def_ret) QCC_PR_ParseWarning(0, "RETURN VALUE ALREADY IN USE"); - QCC_PR_Statement (&pr_opcodes[OP_STORE_F], ao, &def_parms[0], NULL); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], ao, &def_parms[0], NULL)); - QCC_PR_Expect("]"); if (QCC_PR_Check("=")) { funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1); @@ -3301,7 +3298,7 @@ reloop: if (nd->type->type != d->type->type) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - QCC_PR_Statement (&pr_opcodes[OP_STORE_V], nd, &def_parms[1], NULL); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], nd, &def_parms[1], NULL)); QCC_PR_Statement (&pr_opcodes[OP_CALL2], funcretr, 0, NULL); qcc_usefulstatement = true; } @@ -3320,6 +3317,36 @@ reloop: { 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_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; + 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; @@ -3365,7 +3392,6 @@ reloop: else QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); - QCC_PR_Expect("]"); d->type = newtype; goto reloop; } @@ -3573,6 +3599,8 @@ reloop: return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL); } } + else + QCC_PR_IncludeChunk(".", false, NULL); } } @@ -3660,10 +3688,29 @@ QCC_def_t *QCC_PR_Term (void) else if (QCC_PR_Check ("&")) { + int st = numstatements; e = QCC_PR_Expression (NOT_PRIORITY); 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) + { +// QCC_PR_ParseWarning(0, "debug: &ent.field"); + 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"); + return e; + } + } +// QCC_PR_ParseWarning(0, "debug: &global"); + e2 = QCC_PR_Statement (&pr_opcodes[OP_GLOBALADDRESS], e, 0, NULL); + e2->type = QCC_PR_PointerType(e->type); return e2; } @@ -3832,7 +3879,7 @@ QCC_def_t *QCC_PR_Expression (int priority) if ( op->associative!=ASSOC_LEFT ) { // if last statement is an indirect, change it to an address of - if (!simplestore && ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I) && statements[numstatements-1].c == e->ofs) + if (!simplestore && ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) && statements[numstatements-1].c == e->ofs) { qcc_usefulstatement=true; statements[numstatements-1].op = OP_ADDRESS; @@ -3882,6 +3929,9 @@ QCC_def_t *QCC_PR_Expression (int priority) type_a = e->type->type; type_b = e2->type->type; +// if (type_a == ev_pointer && type_b == ev_pointer) +// QCC_PR_ParseWarning(0, "Debug: pointer op pointer"); + if (op->name[0] == '.')// field access gets type from field { if (e2->type->aux_type) @@ -3912,7 +3962,11 @@ QCC_def_t *QCC_PR_Expression (int priority) {//assignment if (op->type_a == &type_pointer) //ent var { - if (e->type->type != ev_pointer || e->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b + 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 = 0; //generic pointer... fixme: is this safe? make sure both sides are equivelent + else if (e->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b c = -200; //don't let the conversion work else c = QCC_canConv(e2, (*op->type_c)->type); @@ -3935,8 +3989,8 @@ QCC_def_t *QCC_PR_Expression (int priority) } else { - c=QCC_canConv(e, (*op->type_a)->type); - c+=QCC_canConv(e2, (*op->type_b)->type); + c=QCC_canConv(e, (*op->type_a)->type); + c+=QCC_canConv(e2, (*op->type_b)->type); } } @@ -4678,9 +4732,12 @@ void QCC_PR_ParseStatement (void) if (keyword_asm && QCC_PR_Check("asm")) { - QCC_PR_Expect ("{"); - - while (!QCC_PR_Check("}")) + if (QCC_PR_Check("{")) + { + while (!QCC_PR_Check("}")) + QCC_PR_ParseAsm (); + } + else QCC_PR_ParseAsm (); return; } @@ -5295,14 +5352,16 @@ void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype) st++; if (st == last) continue; //erm... end of function doesn't count as unreachable. -/* - if (statements[st].op == OP_GOTO) //inefficient compiler, we can ignore this. - continue; - if (statements[st].op == OP_DONE) //inefficient compiler, we can ignore this. - continue; - if (statements[st].op == OP_RETURN) //inefficient compiler, we can ignore this. - continue; -*/ + + if (!opt_compound_jumps) + { //we can ignore single statements like these without compound jumps (compound jumps correctly removes all). + if (statements[st].op == OP_GOTO) //inefficient compiler, we can ignore this. + continue; + if (statements[st].op == OP_DONE) //inefficient compiler, we can ignore this. + continue; + if (statements[st].op == OP_RETURN) //inefficient compiler, we can ignore this. + continue; + } //make sure something goes to just after this return. for (st2 = first; st2 < last; st2++) @@ -5654,6 +5713,9 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) locals_start = locals_end = OFS_PARM0; //hmm... return f; } + + if (type->num_parms < 0) + QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body"); f->builtin = 0; // @@ -5729,7 +5791,6 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) if (QCC_PR_Check ("asm")) { QCC_PR_Expect ("{"); - while (!QCC_PR_Check("}")) QCC_PR_ParseAsm (); } @@ -5887,8 +5948,8 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_GE, index, QCC_MakeFloatDef((float)mid), NULL); - QCC_PR_Statement(pr_opcodes+OP_IF, eq, 0, &st); + eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef((float)mid), NULL); + QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st); } else st = NULL; @@ -5907,6 +5968,8 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 1); + pr_scope = func; + df = &functions[numfunctions]; numfunctions++; @@ -5917,22 +5980,24 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) df->numparms = 1; df->parm_start = numpr_globals; index = QCC_PR_GetDef(type_float, "index___", func, true, 1); + index->references++; + temp = QCC_PR_GetDef(type_float, "div3___", func, true, 1); locals_end = numpr_globals; df->locals = locals_end - df->parm_start; - temp = QCC_GetTemp(type_float); QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp); - QCC_PR_Statement3(pr_opcodes+OP_BITAND, temp, temp, temp); + QCC_PR_Statement3(pr_opcodes+OP_BITAND, temp, temp, temp);//round down to int - QCC_PR_ArrayRecurseDivideUsingVectors(array, index, 0, (array->arraysize+2)/3); //round up + QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up - QCC_PR_Statement(pr_opcodes+OP_DONE, QCC_MakeFloatDef(0), 0, NULL); + 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_DONE, 0, 0, NULL); //err... we didn't find it, give up. G_FUNCTION(func->ofs) = df - functions; func->initialized = 1; return func; } -func_t QCC_PR_EmitArrayGetFunction(char *arrayname) +void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) { QCC_def_t *vectortrick; QCC_dfunction_t *df; @@ -5950,23 +6015,24 @@ func_t QCC_PR_EmitArrayGetFunction(char *arrayname) else vectortrick = NULL; + pr_scope = scope; + df = &functions[numfunctions]; numfunctions++; df->s_file = 0; - df->s_name = 0; + df->s_name = QCC_CopyString(scope->name); df->first_statement = numstatements; df->parm_size[0] = 1; df->numparms = 1; df->parm_start = numpr_globals; index = QCC_PR_GetDef(type_float, "indexg___", def, true, 1); - locals_end = numpr_globals; - df->locals = locals_end - df->parm_start; + + G_FUNCTION(scope->ofs) = df - functions; if (vectortrick) { QCC_def_t *div3, *ret; - def->type = type_vector; eq = QCC_PR_Statement(pr_opcodes+OP_GE, index, QCC_MakeFloatDef((float)def->arraysize), NULL); QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st); @@ -5977,10 +6043,11 @@ func_t QCC_PR_EmitArrayGetFunction(char *arrayname) div3 = QCC_PR_Statement(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), NULL); QCC_PR_Statement3(pr_opcodes+OP_BITAND, div3, div3, div3); - QCC_PR_Statement3(pr_opcodes+OP_STORE_F, div3, &def_parms[0], NULL); + QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL); QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL); vectortrick->references++; - ret = QCC_GetTemp(type_vector); + ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1); + ret->references+=4; QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL); div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, div3, QCC_MakeFloatDef(3), NULL); @@ -6012,9 +6079,13 @@ func_t QCC_PR_EmitArrayGetFunction(char *arrayname) QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL); + QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); + + locals_end = numpr_globals; + df->locals = locals_end - df->parm_start; - return df - functions; + QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start); } void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t *value, int min, int max) @@ -6051,18 +6122,19 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t } } -func_t QCC_PR_EmitArraySetFunction(char *arrayname) +void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) { QCC_dfunction_t *df; QCC_def_t *def, *index, *value; def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0); + pr_scope = scope; df = &functions[numfunctions]; numfunctions++; df->s_file = 0; - df->s_name = 0; + df->s_name = QCC_CopyString(scope->name); df->first_statement = numstatements; df->parm_size[0] = 1; df->parm_size[1] = def->type->size; @@ -6073,6 +6145,8 @@ func_t QCC_PR_EmitArraySetFunction(char *arrayname) locals_end = numpr_globals; df->locals = locals_end - df->parm_start; + G_FUNCTION(scope->ofs) = df - functions; + QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index); QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize); @@ -6080,7 +6154,7 @@ func_t QCC_PR_EmitArraySetFunction(char *arrayname) - return df - functions; + QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start); } //register a def, and all of it's sub parts. @@ -6239,12 +6313,12 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a 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->constant = false; - if (pr_scope) + if (scope) Hash_Add(&localstable, first->name, first); else Hash_Add(&globalstable, first->name, first); - if (!pr_scope && asmfile) + if (!scope && asmfile) fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name); } @@ -6526,6 +6600,7 @@ void QCC_PR_ParseDefs (char *classname) pbool noref = false; pbool nosave = false; pbool allocatenew = true; + int ispointer; gofs_t oldglobals; int arraysize; @@ -6683,7 +6758,14 @@ void QCC_PR_ParseDefs (char *classname) do { - if (QCC_PR_Check (";")) + if (QCC_PR_Check ("*")) + { + ispointer = 1; + while(QCC_PR_Check ("*")) + ispointer++; + name = QCC_PR_ParseName (); + } + else if (QCC_PR_Check (";")) { if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct)) { @@ -6696,9 +6778,13 @@ void QCC_PR_ParseDefs (char *classname) // } QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name"); name = NULL; + ispointer = false; } else + { name = QCC_PR_ParseName (); + ispointer = false; + } if (QCC_PR_Check("::") && !classname) { @@ -6745,7 +6831,20 @@ void QCC_PR_ParseDefs (char *classname) pr_classtype = NULL; oldglobals = numpr_globals; - def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize); + + if (ispointer) + { + parm = type; + while(ispointer) + { + ispointer--; + parm = QCC_PointerTypeTo(parm); + } + + def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize); + } + else + def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize); if (!def) QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname); @@ -6770,10 +6869,17 @@ void QCC_PR_ParseDefs (char *classname) // check for an initialization if (type->type == ev_function && (pr_scope || !constant)) { - def->initialized = 1; //fake function - G_FUNCTION(def->ofs) = 0; if ( QCC_PR_Check ("=") ) QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may only be used as pointers"); + + d = def; //apply to ALL elements + while(d) + { + d->initialized = 1; //fake function + G_FUNCTION(d->ofs) = 0; + d = d->next; + } + continue; } diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index d35874107..d61bf7c67 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -213,6 +213,7 @@ void QCC_PR_NewLine (pbool incomment) } else if (!strncmp(directive, "if", 2)) { + int origionalline = pr_source_line; pr_file_p = directive+2; if (!strncmp(pr_file_p, "def ", 4)) { @@ -263,8 +264,15 @@ void QCC_PR_NewLine (pbool incomment) { while (1) { - while(*pr_file_p==' ' || *pr_file_p == '\t') + while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t')) pr_file_p++; + + if (!*pr_file_p) + { + pr_source_line = origionalline; + QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif"); + } + if (*pr_file_p == '#') { pr_file_p++; @@ -298,6 +306,8 @@ void QCC_PR_NewLine (pbool incomment) } else if (!strncmp(directive, "else", 4)) { + int origionalline = pr_source_line; + ifs -= 1; level = 1; @@ -307,8 +317,15 @@ void QCC_PR_NewLine (pbool incomment) } while (1) { - while(*pr_file_p==' ' || *pr_file_p == '\t') + while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t')) pr_file_p++; + + if (!*pr_file_p) + { + pr_source_line = origionalline; + QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif"); + } + if (*pr_file_p == '#') { pr_file_p++; @@ -514,16 +531,39 @@ void QCC_PR_NewLine (pbool incomment) while(*pr_file_p <= ' ') pr_file_p++; - QCC_PR_LexString(); - printf("Including: %s\n", pr_token); - QCC_Include(pr_token); + *msg = '\0'; + if (*pr_file_p == '\"') + { + pr_file_p++; + for (a=0;a<1023;a++) + { + if (*pr_file_p == '\"') + break; + msg[a] = *pr_file_p++; + } + msg[a] = '\0'; + } + else if (*pr_file_p == '<') + { + pr_file_p++; + for (a=0;a<1023;a++) + { + if (*pr_file_p == '>') + break; + msg[a] = *pr_file_p++; + } + msg[a] = '\0'; + } + else + QCC_PR_ParseError(0, "Not a string literal"); + printf("Including: %s\n", msg); + QCC_Include(msg); pr_file_p++; - for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++) - msg[a] = pr_file_p[a]; + while(*pr_file_p != '\n' && *pr_file_p != '\0' && *pr_file_p <= ' ') + pr_file_p++; - msg[a-1] = '\0'; while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line { @@ -827,6 +867,12 @@ void QCC_PR_LexString (void) c = '"'; else if (c == 't') c = '\t'; + else if (c == 'a') + c = '\a'; + else if (c == 'v') + c = '\v'; + else if (c == 'f') + c = '\f'; else if (c == 's' || c == 'b') { texttype ^= 128; @@ -880,7 +926,11 @@ void QCC_PR_LexString (void) QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1); while(*pr_file_p && *pr_file_p <= ' ') + { + if (*pr_file_p == '\n') + QCC_PR_NewLine(false); pr_file_p++; + } if (*pr_file_p == '\"') //have annother go { pr_file_p++; @@ -2556,6 +2606,16 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) return ftype; return QCC_PR_FindType (ftype); } +QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto) +{ + QCC_type_t *ptype; + char name[128]; + sprintf(name, "*%s", pointsto->name); + ptype = QCC_PR_NewType(name, ev_pointer); + ptype->aux_type = pointsto; + return QCC_PR_FindType (ptype); +} + QCC_type_t *QCC_PR_ParseType (int newtype) { QCC_type_t *newparm; diff --git a/engine/qclib/qccguistuff.c b/engine/qclib/qccguistuff.c index 87f714d27..eefe78abd 100644 --- a/engine/qclib/qccguistuff.c +++ b/engine/qclib/qccguistuff.c @@ -31,7 +31,7 @@ void GoToDefinition(char *name) if (def->type->type == ev_function && def->constant) { fnc = &functions[((int *)qcc_pr_globals)[def->ofs]]; - if (fnc->first_statement>=0) + if (fnc->first_statement>=0 && fnc->s_file) { EditFile(fnc->s_file+strings, statement_linenums[fnc->first_statement]); return; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index cb61b9728..bd436bdbc 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -26,13 +26,13 @@ void FS_CloseFromMem(void *mem); struct qcc_includechunk_s *currentchunk; -unsigned int MAX_REGS = 32768; +unsigned int MAX_REGS; -int MAX_STRINGS = 1000000; -int MAX_GLOBALS = 16384; -int MAX_FIELDS = 1024; -int MAX_STATEMENTS = 65536; -int MAX_FUNCTIONS = 8192; +int MAX_STRINGS; +int MAX_GLOBALS; +int MAX_FIELDS; +int MAX_STATEMENTS; +int MAX_FUNCTIONS; int MAX_CONSTANTS; int max_temps; @@ -1486,15 +1486,18 @@ int QCC_PR_FinishCompilation (void) { if (!strncmp(d->name, "ArrayGet*", 9)) { - G_FUNCTION(d->ofs) = QCC_PR_EmitArrayGetFunction(d->name+9); + QCC_PR_EmitArrayGetFunction(d, d->name+9); + pr_scope = NULL; } else if (!strncmp(d->name, "ArraySet*", 9)) { - G_FUNCTION(d->ofs) = QCC_PR_EmitArraySetFunction(d->name+9); + QCC_PR_EmitArraySetFunction(d, d->name+9); + pr_scope = NULL; } else if (!strncmp(d->name, "Class*", 6)) { - G_FUNCTION(d->ofs) = QCC_PR_EmitClassFromFunction(d, d->name+6); + QCC_PR_EmitClassFromFunction(d, d->name+6); + pr_scope = NULL; } else { @@ -1507,6 +1510,7 @@ int QCC_PR_FinishCompilation (void) bodylessfuncs = true; } } + pr_scope = NULL; return !errors; } @@ -2474,7 +2478,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine MAX_REGS = 65536; MAX_STRINGS = 1000000; - MAX_GLOBALS = 16384; + MAX_GLOBALS = 32768; MAX_FIELDS = 2048; MAX_STATEMENTS = 0x20000; MAX_FUNCTIONS = 16384;