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
This commit is contained in:
Spoike 2004-11-04 04:19:10 +00:00
parent 5031c2a92f
commit e2ef3f2b65
6 changed files with 285 additions and 108 deletions

View File

@ -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
};

View File

@ -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);
//=============================================================================

View File

@ -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, "<ARRAY>", "GET_POINTER", -1, ASSOC_LEFT, &type_void, &type_integer, &type_pointer},
{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, "=", "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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;