mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 20:11:44 +00:00
pointer arithmetic.
fix issue with classes not doing nonvirtual properly. fix virtual functions existing separately from basic fields. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4642 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
45545825a4
commit
3d71834373
5 changed files with 133 additions and 45 deletions
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue