int lineno;
int block;
int scopeLevel;
+int seqPoint;
-symbol *returnLabel; /* function return label */
-symbol *entryLabel; /* function entry label */
+symbol *returnLabel; /* function return label */
+symbol *entryLabel; /* function entry label */
/*-----------------------------------------------------------------*/
/* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *);
-operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *,int);
-operand *geniCodeArray2Ptr (operand *);
+operand *geniCodeAssign (operand *, operand *, int, int);
+static operand *geniCodeArray (operand *, operand *,int);
+static operand *geniCodeArray2Ptr (operand *);
operand *geniCodeRValue (operand *, bool);
operand *geniCodeDerefPtr (operand *,int);
int isLvaluereq(int lvl);
+void setOClass (sym_link * ptr, sym_link * spec);
+static operand *geniCodeCast (sym_link *, operand *, bool);
#define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
/* forward definition of ic print functions */
PRINTFUNC (picJumpTable);
PRINTFUNC (picInline);
PRINTFUNC (picReceive);
+PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
iCodeTable codeTable[] =
{
{RRC, "rrc", picGenericOne, NULL},
{RLC, "rlc", picGenericOne, NULL},
{GETHBIT, "ghbit", picGenericOne, NULL},
+ {GETABIT, "gabit", picGenericOne, NULL},
+ {GETBYTE, "gbyte", picGenericOne, NULL},
+ {GETWORD, "gword", picGenericOne, NULL},
{UNARYMINUS, "-", picGenericOne, NULL},
{IPUSH, "push", picGenericOne, NULL},
{IPOP, "pop", picGenericOne, NULL},
{RECEIVE, "recv", picReceive, NULL},
{SEND, "send", picGenericOne, NULL},
{ARRAYINIT, "arrayInit", picGenericOne, NULL},
+ {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+ {CRITICAL, "critical_start", picCritical, NULL},
+ {ENDCRITICAL, "critical_end", picEndCritical, NULL},
+ {SWAP, "swap", picGenericOne, NULL}
};
/*-----------------------------------------------------------------*/
/* checkConstantRange: check a constant against the type */
/*-----------------------------------------------------------------*/
+
/* pedantic=0: allmost anything is allowed as long as the absolute
value is within the bit range of the type, and -1 is treated as
0xf..f for unsigned types (e.g. in assign)
pedantic>1: "char c=200" is not allowed (evaluates to -56)
*/
-void checkConstantRange(sym_link *ltype, value *val, char *msg,
- int pedantic) {
+void checkConstantRange(sym_link *ltype, value *val, char *msg,
+ int pedantic) {
double max;
int warnings=0;
int negative=0;
max = pow ((double)2.0, (double)bitsForType(ltype));
- if (SPEC_LONG(val->type)) {
- if (SPEC_USIGN(val->type)) {
+ if (IS_LONG(val->type)) {
+ if (IS_UNSIGNED(val->type)) {
v=SPEC_CVAL(val->type).v_ulong;
} else {
v=SPEC_CVAL(val->type).v_long;
}
} else {
- if (SPEC_USIGN(val->type)) {
+ if (IS_UNSIGNED(val->type)) {
v=SPEC_CVAL(val->type).v_uint;
} else {
v=SPEC_CVAL(val->type).v_int;
pedantic=2;
#endif
- if (SPEC_NOUN(ltype)==FLOAT) {
+ if (IS_FLOAT(ltype)) {
+ // anything will do
+ return;
+ }
+
+ if (IS_FIXED(ltype)) {
// anything will do
return;
}
- if (!SPEC_USIGN(val->type) && v<0) {
+ if (!IS_UNSIGNED(val->type) && v<0) {
negative=1;
- if (SPEC_USIGN(ltype) && (pedantic>1)) {
+ if (IS_UNSIGNED(ltype) && (pedantic>1)) {
warnings++;
}
v=-v;
}
// if very pedantic: "char c=200" is not allowed
- if (pedantic>1 && !SPEC_USIGN(ltype)) {
+ if (pedantic>1 && !IS_UNSIGNED(ltype)) {
max = max/2 + negative;
}
#if 0 // temporary disabled, leaving the warning as a reminder
if (warnings) {
- SNPRINTF (message, sizeof(message), "for %s %s in %s",
- SPEC_USIGN(ltype) ? "unsigned" : "signed",
- nounName(ltype), msg);
+ SNPRINTF (message, sizeof(message), "for %s %s in %s",
+ IS_UNSIGNED(ltype) ? "unsigned" : "signed",
+ nounName(ltype), msg);
werror (W_CONST_RANGE, message);
if (pedantic>1)
/*-----------------------------------------------------------------*/
/* operandName - returns the name of the operand */
/*-----------------------------------------------------------------*/
-int
+int
printOperand (operand * op, FILE * file)
{
sym_link *opetype;
case VALUE:
opetype = getSpec (operandType (op));
- if (SPEC_NOUN (opetype) == V_FLOAT)
- fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
+ if (IS_FLOAT (opetype))
+ fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
+ if (IS_FIXED16X16 (opetype))
+ fprintf (file, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
else
- fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
+ fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
printTypeChain (operandType (op), file);
fprintf (file, "}");
break;
case SYMBOL:
#define REGA 1
-#ifdef REGA
- fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
- (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
- op->key,
- OP_LIVEFROM (op), OP_LIVETO (op),
- OP_SYMBOL (op)->stack,
- op->isaddr, OP_SYMBOL (op)->isreqv,
- OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
- OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
- );
+//#if REGA /* { */
+ if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
+ fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
+ (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
+ op->key,
+ OP_LIVEFROM (op), OP_LIVETO (op),
+ OP_SYMBOL (op)->stack,
+ op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
+ OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
+ OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
+ );
{
- fprintf (file, "{");
- printTypeChain (operandType (op), file);
- if (SPIL_LOC (op) && IS_ITEMP (op))
- fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
- fprintf (file, "}");
+ fprintf (file, "{");
+ printTypeChain (operandType (op), file);
+ if (SPIL_LOC (op) && IS_ITEMP (op))
+ fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
+ fprintf (file, "}");
}
/* if assigned to registers */
if (OP_SYMBOL (op)->nRegs)
- {
- if (OP_SYMBOL (op)->isspilt)
- {
- if (!OP_SYMBOL (op)->remat)
- if (OP_SYMBOL (op)->usl.spillLoc)
- fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
- OP_SYMBOL (op)->usl.spillLoc->rname :
- OP_SYMBOL (op)->usl.spillLoc->name));
- else
- fprintf (file, "[err]");
- else
- fprintf (file, "[remat]");
- }
- else
- {
- int i;
- fprintf (file, "[");
- for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
- fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
- fprintf (file, "]");
- }
- }
-#else
- fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
- OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+ {
+ if (OP_SYMBOL (op)->isspilt)
+ {
+ if (!OP_SYMBOL (op)->remat)
+ if (OP_SYMBOL (op)->usl.spillLoc)
+ fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+ OP_SYMBOL (op)->usl.spillLoc->rname :
+ OP_SYMBOL (op)->usl.spillLoc->name));
+ else
+ fprintf (file, "[err]");
+ else
+ fprintf (file, "[remat]");
+ }
+ else
+ {
+ int i;
+ fprintf (file, "[");
+ for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+ fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+ fprintf (file, "]");
+ }
+ }
+//#else /* } else { */
+ } else {
+ /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
+ fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+
+ if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
+ {
+ fprintf (file, "[lr%d:%d so:%d]",
+ OP_LIVEFROM (op), OP_LIVETO (op),
+ OP_SYMBOL (op)->stack);
+ }
+
+ if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
+ {
+ fprintf (file, "{");
+ printTypeChain (operandType (op), file);
+ if (SPIL_LOC (op) && IS_ITEMP (op))
+ fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
+ fprintf (file, "}");
+ }
+
/* if assigned to registers */
- if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
- {
- int i;
- fprintf (file, "[");
- for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
- fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
- OP_SYMBOL (op)->regs[i]->name :
- "err"));
- fprintf (file, "]");
- }
-#endif
+ if (OP_SYMBOL (op)->nRegs)
+ {
+ if (OP_SYMBOL (op)->isspilt)
+ {
+ if (!OP_SYMBOL (op)->remat)
+ if (OP_SYMBOL (op)->usl.spillLoc)
+ fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+ OP_SYMBOL (op)->usl.spillLoc->rname :
+ OP_SYMBOL (op)->usl.spillLoc->name));
+ else
+ fprintf (file, "[err]");
+ else
+ fprintf (file, "[remat]");
+ }
+ else
+ {
+ int i;
+ fprintf (file, "[");
+ for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+ fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+ fprintf (file, "]");
+ }
+ }
+//#endif /* } */
+ }
break;
case TYPE:
if (IC_RIGHT (ic))
{
if (IS_ITEMP (IC_LEFT (ic)))
- fprintf (of, " offsetAdd ");
+ fprintf (of, " offsetAdd ");
else
- fprintf (of, " , ");
+ fprintf (of, " , ");
printOperand (IC_RIGHT (ic), of);
}
if (IS_ITEMP (IC_LEFT (ic)))
if (ic->op == SEND || ic->op == RECEIVE) {
fprintf(of,"{argreg = %d}",ic->argreg);
}
+ if (ic->op == IPUSH) {
+ fprintf(of,"{parmPush = %d}",ic->parmPush);
+ }
fprintf (of, "\n");
}
{
fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
if (IC_FALSE (ic))
- fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
+ fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
}
}
fprintf (of, "\n");
}
+PRINTFUNC (picDummyRead)
+{
+ fprintf (of, "\t");
+ fprintf (of, "%s ", s);
+ printOperand (IC_RIGHT (ic), of);
+ fprintf (of, "\n");
+}
+
+PRINTFUNC (picCritical)
+{
+ fprintf (of, "\t");
+ if (IC_RESULT (ic))
+ printOperand (IC_RESULT (ic), of);
+ else
+ fprintf (of, "(stack)");
+ fprintf (of, " = %s ", s);
+ fprintf (of, "\n");
+}
+
+PRINTFUNC (picEndCritical)
+{
+ fprintf (of, "\t");
+ fprintf (of, "%s = ", s);
+ if (IC_RIGHT (ic))
+ printOperand (IC_RIGHT (ic), of);
+ else
+ fprintf (of, "(stack)");
+ fprintf (of, "\n");
+}
+
/*-----------------------------------------------------------------*/
/* piCode - prints one iCode */
/*-----------------------------------------------------------------*/
-int
+int
piCode (void *item, FILE * of)
{
iCode *ic = item;
of = stdout;
icTab = getTableEntry (ic->op);
- fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
- ic->filename, ic->lineno,
- ic->seq, ic->key, ic->depth, ic->supportRtn);
+ fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+ ic->filename, ic->lineno,
+ ic->seq, ic->key, ic->depth, ic->supportRtn);
icTab->iCodePrint (of, ic, icTab->printName);
return 1;
}
void PICC(iCode *ic)
{
- printiCChain(ic,stdout);
+ printiCChain(ic,stdout);
}
/*-----------------------------------------------------------------*/
/* printiCChain - prints intermediate code for humans */
/*-----------------------------------------------------------------*/
-void
+void
printiCChain (iCode * icChain, FILE * of)
{
iCode *loop;
for (loop = icChain; loop; loop = loop->next)
{
if ((icTab = getTableEntry (loop->op)))
- {
- fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
- loop->filename, loop->lineno,
- loop->seq, loop->key, loop->depth, loop->supportRtn);
+ {
+ fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
+ loop->filename, loop->lineno,
+ loop->seq, loop->key, loop->depth, loop->supportRtn);
- icTab->iCodePrint (of, loop, icTab->printName);
- }
+ icTab->iCodePrint (of, loop, icTab->printName);
+ }
}
}
ic = Safe_alloc ( sizeof (iCode));
+ ic->seqPoint = seqPoint;
ic->lineno = lineno;
ic->filename = filename;
ic->block = block;
/*-----------------------------------------------------------------*/
iCode *
newiCodeCondition (operand * condition,
- symbol * trueLabel,
- symbol * falseLabel)
+ symbol * trueLabel,
+ symbol * falseLabel)
{
iCode *ic;
{
SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
}
-
+
itmp = newSymbol (buffer, 1);
strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
itmp->isitmp = 1;
{
symbol *itmplbl;
- /* check if this alredy exists */
+ /* check if this already exists */
if (s && (itmplbl = findSym (LabelTab, NULL, s)))
return itmplbl;
if (s)
{
- itmplbl = newSymbol (s, 1);
+ itmplbl = newSymbol (s, 1);
}
else
{
/*-----------------------------------------------------------------*/
/* initiCode - initialises some iCode related stuff */
/*-----------------------------------------------------------------*/
-void
+void
initiCode ()
{
iCodeTable *
getTableEntry (int oper)
{
- int i;
+ unsigned i;
for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
if (oper == codeTable[i].icode)
/* copy the type information */
if (type)
itmp->etype = getSpec (itmp->type = (throwType ? type :
- copyLinkChain (type)));
+ copyLinkChain (type)));
if (IS_LITERAL (itmp->etype))
{
SPEC_SCLS (itmp->etype) = S_REGISTER;
return op->operand.typeOperand;
default:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- " operand type not known ");
- assert (0); /* should never come here */
+ " operand type not known ");
+ assert (0); /* should never come here */
/* Just to keep the compiler happy */
return (sym_link *) 0;
}
/*-----------------------------------------------------------------*/
/* isParamterToCall - will return 1 if op is a parameter to args */
/*-----------------------------------------------------------------*/
-int
+int
isParameterToCall (value * args, operand * op)
{
value *tval = args;
wassert (IS_SYMOP(op));
-
+
while (tval)
{
if (tval->sym &&
- isSymbolEqual (op->operand.symOperand, tval->sym))
- return 1;
+ isSymbolEqual (op->operand.symOperand, tval->sym))
+ return 1;
tval = tval->next;
}
return 0;
/*-----------------------------------------------------------------*/
/* isOperandGlobal - return 1 if operand is a global variable */
/*-----------------------------------------------------------------*/
-int
+int
isOperandGlobal (operand * op)
{
if (!op)
/*-----------------------------------------------------------------*/
/* isOperandVolatile - return 1 if the operand is volatile */
/*-----------------------------------------------------------------*/
-int
+int
isOperandVolatile (operand * op, bool chkTemp)
{
sym_link *optype;
if (IS_ITEMP (op) && !chkTemp)
return 0;
- return IS_VOLATILE(operandType(op));
+ opetype = getSpec (optype = operandType (op));
+
+ if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
+ return 1;
+
+ if (IS_VOLATILE (opetype))
+ return 1;
+ return 0;
}
/*-----------------------------------------------------------------*/
/* isOperandLiteral - returns 1 if an operand contains a literal */
/*-----------------------------------------------------------------*/
-int
+int
isOperandLiteral (operand * op)
{
sym_link *opetype;
/*-----------------------------------------------------------------*/
/* isOperandInFarSpace - will return true if operand is in farSpace */
/*-----------------------------------------------------------------*/
-bool
+bool
isOperandInFarSpace (operand * op)
{
sym_link *etype;
if (!IS_TRUE_SYMOP (op))
{
if (SPIL_LOC (op))
- etype = SPIL_LOC (op)->etype;
+ etype = SPIL_LOC (op)->etype;
else
- return FALSE;
+ return FALSE;
}
else
{
/*------------------------------------------------------------------*/
/* isOperandInDirSpace - will return true if operand is in dirSpace */
/*------------------------------------------------------------------*/
-bool
+bool
isOperandInDirSpace (operand * op)
{
sym_link *etype;
if (!IS_TRUE_SYMOP (op))
{
if (SPIL_LOC (op))
- etype = SPIL_LOC (op)->etype;
+ etype = SPIL_LOC (op)->etype;
else
- return FALSE;
+ return FALSE;
}
else
{
/*--------------------------------------------------------------------*/
/* isOperandInCodeSpace - will return true if operand is in codeSpace */
/*--------------------------------------------------------------------*/
-bool
+bool
isOperandInCodeSpace (operand * op)
{
sym_link *etype;
if (!IS_TRUE_SYMOP (op))
{
if (SPIL_LOC (op))
- etype = SPIL_LOC (op)->etype;
+ etype = SPIL_LOC (op)->etype;
else
- return FALSE;
+ return FALSE;
}
else
{
/*-----------------------------------------------------------------*/
/* isOperandOnStack - will return true if operand is on stack */
/*-----------------------------------------------------------------*/
-bool
+bool
isOperandOnStack (operand * op)
{
sym_link *etype;
return FALSE;
}
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output */
+/* storage class are expensive */
+/*-----------------------------------------------------------------*/
+bool
+isOclsExpensive (struct memmap *oclass)
+{
+ if (port->oclsExpense)
+ return port->oclsExpense (oclass) > 0;
+
+ /* In the absence of port specific guidance, assume only */
+ /* farspace is expensive. */
+ return IN_FARSPACE (oclass);
+}
+
+/*-----------------------------------------------------------------*/
+/* isiCodeInFunctionCall - return TRUE if an iCode is between a */
+/* CALL/PCALL and the first IPUSH/SEND associated with the call */
+/*-----------------------------------------------------------------*/
+int
+isiCodeInFunctionCall (iCode * ic)
+{
+ iCode * lic = ic;
+
+ /* Find the next CALL/PCALL */
+ while (lic)
+ {
+ if (lic->op == CALL || lic->op == PCALL)
+ break;
+ lic = lic->next;
+ }
+
+ if (!lic)
+ return FALSE;
+
+ /* A function call was found. Scan backwards and see if an */
+ /* IPUSH or SEND is encountered */
+ while (ic)
+ {
+ if (lic != ic && (ic->op == CALL || ic->op == PCALL))
+ return FALSE;
+ if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
+ return TRUE;
+ ic = ic->prev;
+ }
+
+ return FALSE;
+}
+
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
-double
+double
operandLitValue (operand * op)
{
assert (isOperandLiteral (op));
*pcount = 0;
/* builtin functions uses only SEND for parameters */
while (ic->op != CALL) {
- assert(ic->op == SEND && ic->builtinSEND);
- ic->generated = 1; /* mark the icode as generated */
- parms[*pcount] = IC_LEFT(ic);
- ic = ic->next;
- (*pcount)++;
+ assert(ic->op == SEND && ic->builtinSEND);
+ ic->generated = 1; /* mark the icode as generated */
+ parms[*pcount] = IC_LEFT(ic);
+ ic = ic->next;
+ (*pcount)++;
}
-
+
ic->generated = 1;
/* make sure this is a builtin function call */
assert(IS_SYMOP(IC_LEFT(ic)));
}
/*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands */
+/* operandOperation - performs operations on operands */
/*-----------------------------------------------------------------*/
operand *
operandOperation (operand * left, operand * right,
- int op, sym_link * type)
+ int op, sym_link * type)
{
sym_link *let , *ret=NULL;
operand *retval = (operand *) 0;
-
+
assert (isOperandLiteral (left));
let = getSpec(operandType(left));
if (right) {
assert (isOperandLiteral (right));
- ret = getSpec(operandType(left));
+ ret = getSpec(operandType(right));
}
switch (op)
{
case '+':
retval = operandFromValue (valCastLiteral (type,
- operandLitValue (left) +
- operandLitValue (right)));
+ operandLitValue (left) +
+ operandLitValue (right)));
break;
case '-':
retval = operandFromValue (valCastLiteral (type,
- operandLitValue (left) -
- operandLitValue (right)));
+ operandLitValue (left) -
+ operandLitValue (right)));
break;
case '*':
+ /*
retval = operandFromValue (valCastLiteral (type,
- operandLitValue (left) *
- operandLitValue (right)));
+ operandLitValue (left) *
+ operandLitValue (right)));
+ This could be all we've to do, but with gcc we've to take care about
+ overflows. Two examples:
+ ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+ significant bits are lost (52 in fraction, 63 bits would be
+ necessary to keep full precision).
+ If the resulting double value is greater than ULONG_MAX (resp.
+ USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+ */
+
+ /* if it is not a specifier then we can assume that */
+ /* it will be an unsigned long */
+ if (IS_INT (type) ||
+ !IS_SPEC (type))
+ {
+ /* long is handled here, because it can overflow with double */
+ if (IS_LONG (type) ||
+ !IS_SPEC (type))
+ /* signed and unsigned mul are the same, as long as the precision
+ of the result isn't bigger than the precision of the operands. */
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) *
+ (TYPE_UDWORD) operandLitValue (right)));
+ else if (IS_UNSIGNED (type)) /* unsigned int */
+ {
+ /* unsigned int is handled here in order to detect overflow */
+ TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+ (TYPE_UWORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+ if (ul != (TYPE_UWORD) ul)
+ werror (W_INT_OVL);
+ }
+ else /* signed int */
+ {
+ /* signed int is handled here in order to detect overflow */
+ TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+ (TYPE_WORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+ if (l != (TYPE_WORD) l)
+ werror (W_INT_OVL);
+ }
+ }
+ else
+ /* all others go here: */
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) *
+ operandLitValue (right)));
break;
case '/':
- if ((unsigned long) operandLitValue (right) == 0)
- {
- werror (E_DIVIDE_BY_ZERO);
- retval = right;
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
+ {
+ werror (E_DIVIDE_BY_ZERO);
+ retval = right;
- }
+ }
else
- retval = operandFromValue (valCastLiteral (type,
- operandLitValue (left) /
- operandLitValue (right)));
+ {
+ if (IS_UNSIGNED (type))
+ {
+ SPEC_USIGN (let) = 1;
+ SPEC_USIGN (ret) = 1;
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) /
+ (TYPE_UDWORD) operandLitValue (right)));
+ }
+ else
+ {
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) /
+ operandLitValue (right)));
+ }
+ }
break;
case '%':
- if ((unsigned long) operandLitValue (right) == 0) {
- werror (E_DIVIDE_BY_ZERO);
- retval = right;
- }
- else
- retval = operandFromLit ((SPEC_USIGN(let) ?
- (unsigned long) operandLitValue (left) :
- (long) operandLitValue (left)) %
- (SPEC_USIGN(ret) ?
- (unsigned long) operandLitValue (right) :
- (long) operandLitValue (right)));
-
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
+ {
+ werror (E_DIVIDE_BY_ZERO);
+ retval = right;
+ }
+ else
+ {
+ if (IS_UNSIGNED (type))
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+ (TYPE_DWORD) operandLitValue (right));
+ }
break;
case LEFT_OP:
- retval = operandFromLit ((SPEC_USIGN(let) ?
- (unsigned long) operandLitValue (left) :
- (long) operandLitValue (left)) <<
- (SPEC_USIGN(ret) ?
- (unsigned long) operandLitValue (right) :
- (long) operandLitValue (right)));
+ /* The number of left shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ retval = operandFromValue (valCastLiteral (type,
+ ((TYPE_UDWORD) operandLitValue (left) <<
+ (TYPE_UDWORD) operandLitValue (right))));
break;
- case RIGHT_OP: {
- double lval = operandLitValue(left), rval = operandLitValue(right);
- double res=0;
- switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
- {
- case 0: // left=unsigned right=unsigned
- res=(unsigned long)lval >> (unsigned long)rval;
- break;
- case 1: // left=unsigned right=signed
- res=(unsigned long)lval >> (signed long)rval;
- break;
- case 2: // left=signed right=unsigned
- res=(signed long)lval >> (unsigned long)rval;
- break;
- case 3: // left=signed right=signed
- res=(signed long)lval >> (signed long)rval;
- break;
- }
- retval = operandFromLit (res);
+ case RIGHT_OP:
+ /* The number of right shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ if (IS_UNSIGNED(let))
+ /* unsigned: logic shift right */
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ /* signed: arithmetic shift right */
+ retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
break;
- }
case EQ_OP:
- retval = operandFromLit (operandLitValue (left) ==
- operandLitValue (right));
+ if (IS_FLOAT (let) ||
+ IS_FLOAT (ret))
+ {
+ retval = operandFromLit (operandLitValue (left) ==
+ operandLitValue (right));
+ }
+ else
+ if (IS_FIXED16X16 (let) ||
+ IS_FIXED16X16 (ret))
+ {
+ retval = operandFromLit (operandLitValue (left) ==
+ operandLitValue (right));
+ }
+ else
+ {
+ /* this op doesn't care about signedness */
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ r = (TYPE_UDWORD) operandLitValue (right);
+ /* In order to correctly compare 'signed int' and 'unsigned int' it's
+ neccessary to strip them to 16 bit.
+ Literals are reduced to their cheapest type, therefore left and
+ right might have different types. It's neccessary to find a
+ common type: int (used for char too) or long */
+ if (!IS_LONG (let) &&
+ !IS_LONG (ret))
+ {
+ r = (TYPE_UWORD) r;
+ l = (TYPE_UWORD) l;
+ }
+ retval = operandFromLit (l == r);
+ }
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
- operandLitValue (right));
+ operandLitValue (right));
break;
case LE_OP:
retval = operandFromLit (operandLitValue (left) <=
- operandLitValue (right));
+ operandLitValue (right));
break;
case NE_OP:
retval = operandFromLit (operandLitValue (left) !=
- operandLitValue (right));
+ operandLitValue (right));
break;
case '>':
retval = operandFromLit (operandLitValue (left) >
- operandLitValue (right));
+ operandLitValue (right));
break;
case GE_OP:
retval = operandFromLit (operandLitValue (left) >=
- operandLitValue (right));
+ operandLitValue (right));
break;
case BITWISEAND:
- retval = operandFromLit ((long)operandLitValue(left) &
- (long)operandLitValue(right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) &
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case '|':
- retval = operandFromLit ((long)operandLitValue (left) |
- (long)operandLitValue (right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) |
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case '^':
- retval = operandFromLit ((long)operandLitValue (left) ^
- (long)operandLitValue (right));
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) ^
+ (TYPE_UDWORD)operandLitValue(right)));
break;
case AND_OP:
retval = operandFromLit (operandLitValue (left) &&
- operandLitValue (right));
+ operandLitValue (right));
break;
case OR_OP:
retval = operandFromLit (operandLitValue (left) ||
- operandLitValue (right));
+ operandLitValue (right));
break;
case RRC:
{
- long i = (long) operandLitValue (left);
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
- retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
- (i << 1));
+ retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
+ (i << 1));
}
break;
case RLC:
{
- long i = (long) operandLitValue (left);
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
- retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
- (i >> 1));
+ retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
+ (i >> 1));
}
break;
+ case GETABIT:
+ retval = operandFromLit (((TYPE_UDWORD)operandLitValue(left) >>
+ (TYPE_UDWORD)operandLitValue(right)) & 1);
+ break;
+ case GETBYTE:
+ retval = operandFromLit (((TYPE_UDWORD)operandLitValue(left) >>
+ (TYPE_UDWORD)operandLitValue(right)) & 0xFF);
+ break;
+ case GETWORD:
+ retval = operandFromLit (((TYPE_UDWORD)operandLitValue(left) >>
+ (TYPE_UDWORD)operandLitValue(right)) & 0xFFFF);
+ break;
+
+ case GETHBIT:
+ retval = operandFromLit (((TYPE_UDWORD)operandLitValue(left) >>
+ ((getSize (let) * 8) - 1)) & 1);
+ break;
case UNARYMINUS:
- retval = operandFromLit (-1 * operandLitValue (left));
+ retval = operandFromValue (valCastLiteral (type,
+ -1 * operandLitValue (left)));
break;
case '~':
- retval = operandFromLit (~((long) operandLitValue (left)));
+ retval = operandFromValue (valCastLiteral (type,
+ ~((TYPE_UDWORD)
+ operandLitValue (left))));
break;
case '!':
default:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- " operandOperation invalid operator ");
+ " operandOperation invalid operator ");
assert (0);
}
/*-----------------------------------------------------------------*/
/* isOperandEqual - compares two operand & return 1 if they r = */
/*-----------------------------------------------------------------*/
-int
+int
isOperandEqual (operand * left, operand * right)
{
/* if the pointers are equal then they are equal */
{
case SYMBOL:
return isSymbolEqual (left->operand.symOperand,
- right->operand.symOperand);
+ right->operand.symOperand);
case VALUE:
- return (floatFromVal (left->operand.valOperand) ==
- floatFromVal (right->operand.valOperand));
+ return (compareType (left->operand.valOperand->type,
+ right->operand.valOperand->type) &&
+ (floatFromVal (left->operand.valOperand) ==
+ floatFromVal (right->operand.valOperand)));
case TYPE:
if (compareType (left->operand.typeOperand,
- right->operand.typeOperand) == 1)
- return 1;
+ right->operand.typeOperand) == 1)
+ return 1;
}
return 0;
/*-------------------------------------------------------------------*/
/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
/*-------------------------------------------------------------------*/
-int
+int
isiCodeEqual (iCode * left, iCode * right)
{
/* if the same pointer */
/* compare all the elements depending on type */
if (left->op != IFX)
- {
- if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
- return 0;
- if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
- return 0;
+ {
+ if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
+ return 0;
+ if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
+ return 0;
- }
+ }
else
- {
- if (!isOperandEqual (IC_COND (left), IC_COND (right)))
- return 0;
- if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
- return 0;
- if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
- return 0;
- }
-
+ {
+ if (!isOperandEqual (IC_COND (left), IC_COND (right)))
+ return 0;
+ if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
+ return 0;
+ if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
+ return 0;
+ }
+
return 1;
}
return 0;
register equivalent for a local symbol */
if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
(IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ !TARGET_IS_HC08 &&
(!(options.model == MODEL_FLAT24)) ) &&
options.stackAuto == 0)
ok = 0;
- if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
- !IS_FUNC (sym->type) && /* not a function */
- !sym->_isparm && /* not a parameter */
- sym->level && /* is a local variable */
- !sym->addrtaken && /* whose address has not been taken */
- !sym->reqv && /* does not already have a reg equivalence */
- !IS_VOLATILE (sym->etype) && /* not declared as volatile */
- !IS_STATIC (sym->etype) && /* and not declared static */
- !sym->islbl && /* not a label */
- ok && /* farspace check */
- !IS_BITVAR (sym->etype) /* not a bit variable */
+ if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
+ !IS_FUNC (sym->type) && /* not a function */
+ !sym->_isparm && /* not a parameter */
+ IS_AUTO (sym) && /* is a local auto variable */
+ !sym->addrtaken && /* whose address has not been taken */
+ !sym->reqv && /* does not already have a reg equivalence */
+ !IS_VOLATILE (sym->etype) && /* not declared as volatile */
+ !sym->islbl && /* not a label */
+ ok /* farspace check */
)
{
and before liveRange calculation */
sym->reqv = newiTempOperand (sym->type, 0);
sym->reqv->key = sym->key;
+ OP_SYMBOL (sym->reqv)->prereqv = sym;
OP_SYMBOL (sym->reqv)->key = sym->key;
OP_SYMBOL (sym->reqv)->isreqv = 1;
OP_SYMBOL (sym->reqv)->islocal = 1;
case EX_LINK:
return operandFromLink (tree->opval.lnk);
+ break;
+
+ default:
+ assert (0);
}
- assert (0);
- /* Just to keep the comiler happy */
+ /* Just to keep the compiler happy */
return (operand *) 0;
}
/*-----------------------------------------------------------------*/
/* setOperandType - sets the operand's type to the given type */
/*-----------------------------------------------------------------*/
-void
+void
setOperandType (operand * op, sym_link * type)
{
/* depending on the type of operand */
case VALUE:
op->operand.valOperand->etype =
- getSpec (op->operand.valOperand->type =
- copyLinkChain (type));
+ getSpec (op->operand.valOperand->type =
+ copyLinkChain (type));
return;
case SYMBOL:
if (op->operand.symOperand->isitmp)
- op->operand.symOperand->etype =
- getSpec (op->operand.symOperand->type =
- copyLinkChain (type));
+ op->operand.symOperand->etype =
+ getSpec (op->operand.symOperand->type =
+ copyLinkChain (type));
else
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "attempt to modify type of source");
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "attempt to modify type of source");
return;
case TYPE:
}
}
+
/*-----------------------------------------------------------------*/
/* Get size in byte of ptr need to access an array */
/*-----------------------------------------------------------------*/
-int
+static int
getArraySizePtr (operand * op)
{
sym_link *ltype = operandType(op);
if(IS_PTR(ltype))
{
int size = getSize(ltype);
- return(IS_GENPTR(ltype)?(size-1):size);
+ return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
}
if(IS_ARRAY(ltype))
{
sym_link *letype = getSpec(ltype);
switch (PTR_TYPE (SPEC_OCLS (letype)))
- {
- case IPOINTER:
- case PPOINTER:
- case POINTER:
- return (PTRSIZE);
- case EEPPOINTER:
- case FPOINTER:
- case CPOINTER:
- case FUNCTION:
- return (FPTRSIZE);
- case GPOINTER:
- return (GPTRSIZE-1);
-
- default:
- return (FPTRSIZE);
- }
+ {
+ case IPOINTER:
+ case PPOINTER:
+ case POINTER:
+ return (PTRSIZE);
+ case EEPPOINTER:
+ case FPOINTER:
+ case CPOINTER:
+ case FUNCTION:
+ return (FPTRSIZE);
+ case GPOINTER:
+ if (GPTRSIZE > FPTRSIZE)
+ return (GPTRSIZE-1);
+ else
+ return (FPTRSIZE);
+
+ default:
+ return (FPTRSIZE);
+ }
}
return (FPTRSIZE);
}
/*-----------------------------------------------------------------*/
/* perform "usual unary conversions" */
/*-----------------------------------------------------------------*/
-operand *
+#if 0
+static operand *
usualUnaryConversions (operand * op)
{
if (IS_INTEGRAL (operandType (op)))
{
if (getSize (operandType (op)) < (unsigned int) INTSIZE)
- {
- /* Widen to int. */
- return geniCodeCast (INTTYPE, op, TRUE);
- }
+ {
+ /* Widen to int. */
+ return geniCodeCast (INTTYPE, op, TRUE);
+ }
}
return op;
}
+#endif
/*-----------------------------------------------------------------*/
/* perform "usual binary conversions" */
/*-----------------------------------------------------------------*/
-sym_link *
-usualBinaryConversions (operand ** op1, operand ** op2)
+
+static sym_link *
+usualBinaryConversions (operand ** op1, operand ** op2,
+ RESULT_TYPE resultType, int op)
{
sym_link *ctype;
sym_link *rtype = operandType (*op2);
sym_link *ltype = operandType (*op1);
-
- ctype = computeType (ltype, rtype);
+
+ ctype = computeType (ltype, rtype, resultType, op);
+
+ switch (op)
+ {
+ case '*':
+ case '/':
+ case '%':
+ if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
+ {
+ /* one byte operations: keep signedness for code generator */
+ return ctype;
+ }
+ break;
+ default:
+ break;
+ }
*op1 = geniCodeCast (ctype, *op1, TRUE);
*op2 = geniCodeCast (ctype, *op2, TRUE);
-
+
return ctype;
}
/* if this is not a temp symbol then */
if (!IS_ITEMP (op) &&
!force &&
- !IN_FARSPACE (SPEC_OCLS (etype)))
+ !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
{
op = operandFromOperand (op);
op->isaddr = 0;
if (IS_SPEC (type) &&
IS_TRUE_SYMOP (op) &&
- (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+ (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
(options.model == MODEL_FLAT24) ))
{
op = operandFromOperand (op);
/*-----------------------------------------------------------------*/
/* geniCodeCast - changes the value from one type to another */
/*-----------------------------------------------------------------*/
-operand *
+static operand *
geniCodeCast (sym_link * type, operand * op, bool implicit)
{
iCode *ic;
return op;
}
+ if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
+ {
+ geniCodeArray2Ptr (op);
+ op->isaddr = 0;
+ }
+
/* if the operand is already the desired type then do nothing */
if (compareType (type, optype) == 1)
return op;
/* if this is a literal then just change the type & return */
if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
- return operandFromValue (valCastLiteral (type,
- operandLitValue (op)));
+ {
+ return operandFromValue (valCastLiteral (type,
+ operandLitValue (op)));
+ }
/* if casting to/from pointers, do some checking */
if (IS_PTR(type)) { // to a pointer
if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
- if (IS_INTEGRAL(optype)) {
- // maybe this is NULL, than it's ok.
- if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
- if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
- // no way to set the storage
- if (IS_LITERAL(optype)) {
- werror(E_LITERAL_GENERIC);
- errors++;
- } else {
- werror(E_NONPTR2_GENPTR);
- errors++;
- }
- } else if (implicit) {
- werror(W_INTEGRAL2PTR_NOCAST);
- errors++;
- }
- }
- } else {
- // shouldn't do that with float, array or structure unless to void
- if (!IS_VOID(getSpec(type)) &&
- !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
- werror(E_INCOMPAT_TYPES);
- errors++;
- }
+ if (IS_INTEGRAL(optype)) {
+ // maybe this is NULL, than it's ok.
+ if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
+ if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
+ // no way to set the storage
+ if (IS_LITERAL(optype)) {
+ werror(E_LITERAL_GENERIC);
+ errors++;
+ } else {
+ werror(E_NONPTR2_GENPTR);
+ errors++;
+ }
+ } else if (implicit) {
+ werror(W_INTEGRAL2PTR_NOCAST);
+ errors++;
+ }
+ }
+ } else {
+ // shouldn't do that with float, array or structure unless to void
+ if (!IS_VOID(getSpec(type)) &&
+ !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
}
} else { // from a pointer to a pointer
- if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
- // if not a pointer to a function
- if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
- if (implicit) { // if not to generic, they have to match
- if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
- werror(E_INCOMPAT_PTYPES);
- errors++;
- }
- }
- }
+ if (IS_GENPTR(type) && IS_VOID(type->next))
+ { // cast to void* is always allowed
+ }
+ else if (IS_GENPTR(optype) && IS_VOID(optype->next))
+ { // cast from void* is always allowed
+ }
+ else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
+ // if not a pointer to a function
+ if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ if (implicit) { // if not to generic, they have to match
+ if (!IS_GENPTR(type) &&
+ !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
+ ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
+ )
+ )
+ {
+ werror(E_INCOMPAT_PTYPES);
+ errors++;
+ }
+ }
+ }
}
}
} else { // to a non pointer
if (IS_PTR(optype)) { // from a pointer
if (implicit) { // sneaky
- if (IS_INTEGRAL(type)) {
- werror(W_PTR2INTEGRAL_NOCAST);
- errors++;
- } else { // shouldn't do that with float, array or structure
- werror(E_INCOMPAT_TYPES);
- errors++;
- }
+ if (IS_INTEGRAL(type)) {
+ werror(W_PTR2INTEGRAL_NOCAST);
+ errors++;
+ } else { // shouldn't do that with float, array or structure
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
}
}
}
}
/* if they are the same size create an assignment */
+
+ /* This seems very dangerous to me, since there are several */
+ /* optimizations (for example, gcse) that don't notice the */
+ /* cast hidden in this assignement and may simplify an */
+ /* iCode to use the original (uncasted) operand. */
+ /* Unfortunately, other things break when this cast is */
+ /* made explicit. Need to fix this someday. */
+ /* -- EEP, 2004/01/21 */
if (getSize (type) == getSize (optype) &&
!IS_BITFIELD (type) &&
!IS_FLOAT (type) &&
!IS_FLOAT (optype) &&
+ !IS_FIXED (type) &&
+ !IS_FIXED (optype) &&
((IS_SPEC (type) && IS_SPEC (optype)) ||
(!IS_SPEC (type) && !IS_SPEC (optype))))
{
-
ic = newiCode ('=', NULL, op);
IC_RESULT (ic) = newiTempOperand (type, 0);
- SPIL_LOC (IC_RESULT (ic)) =
- (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
+ if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
+ SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
IC_RESULT (ic)->isaddr = 0;
}
else
{
ic = newiCode (CAST, operandFromLink (type),
- geniCodeRValue (op, FALSE));
+ geniCodeRValue (op, FALSE));
IC_RESULT (ic) = newiTempOperand (type, 0);
}
/* preserve the storage class & output class */
/* of the original variable */
restype = getSpec (operandType (IC_RESULT (ic)));
- if (!IS_LITERAL(opetype))
+ if (!IS_LITERAL(opetype) &&
+ !IS_BIT(opetype))
+ {
SPEC_SCLS (restype) = SPEC_SCLS (opetype);
- SPEC_OCLS (restype) = SPEC_OCLS (opetype);
-
+ SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+ }
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
/*-----------------------------------------------------------------*/
/* geniCodeLabel - will create a Label */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeLabel (symbol * label)
{
iCode *ic;
/*-----------------------------------------------------------------*/
/* geniCodeGoto - will create a Goto */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeGoto (symbol * label)
{
iCode *ic;
/*-----------------------------------------------------------------*/
/* geniCodeMultiply - gen intermediate code for multiplication */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeMultiply (operand * left, operand * right,int resultIsInt)
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
/* if they are both literal then we know the result */
if (IS_LITERAL (letype) && IS_LITERAL (retype))
return operandFromValue (valMult (left->operand.valOperand,
- right->operand.valOperand));
+ right->operand.valOperand));
if (IS_LITERAL(retype)) {
- p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+ p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
}
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, resultType, '*');
#if 1
rtype = operandType (right);
retype = getSpec (rtype);
ltype = operandType (left);
letype = getSpec (ltype);
#endif
- if (resultIsInt)
- {
- SPEC_NOUN(getSpec(resType))=V_INT;
- }
/* if the right is a literal & power of 2 */
/* then make it a left shift */
- /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
- efficient in most cases than 2 bytes result = 2 bytes << literal
+ /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
+ efficient in most cases than 2 bytes result = 2 bytes << literal
if port has 1 byte muldiv */
- if (p2 && !IS_FLOAT (letype) &&
- !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
- (port->support.muldiv == 1)))
- {
- if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
- {
- /* LEFT_OP need same size for left and result, */
- left = geniCodeCast (resType, left, TRUE);
- ltype = operandType (left);
- }
+ if (p2 && !IS_FLOAT (letype) && !IS_FIXED (letype)
+ && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
+ && (port->support.muldiv == 1))
+ && strcmp (port->target, "pic16") != 0 /* don't shift for pic */
+ && strcmp (port->target, "pic14") != 0)
+ {
+ if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
+ {
+ /* LEFT_OP need same size for left and result, */
+ left = geniCodeCast (resType, left, TRUE);
+ ltype = operandType (left);
+ }
ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
}
else
{
- ic = newiCode ('*', left, right); /* normal multiplication */
+ ic = newiCode ('*', left, right); /* normal multiplication */
/* if the size left or right > 1 then support routine */
if (getSize (ltype) > 1 || getSize (rtype) > 1)
- ic->supportRtn = 1;
+ ic->supportRtn = 1;
}
IC_RESULT (ic) = newiTempOperand (resType, 1);
/*-----------------------------------------------------------------*/
/* geniCodeDivision - gen intermediate code for division */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeDivision (operand * left, operand * right)
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
sym_link *ltype = operandType (left);
sym_link *letype = getSpec (ltype);
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, resultType, '/');
- /* if the right is a literal & power of 2
- and left is unsigned then make it a
+ /* if the right is a literal & power of 2
+ and left is unsigned then make it a
right shift */
if (IS_LITERAL (retype) &&
!IS_FLOAT (letype) &&
- SPEC_USIGN(letype) &&
- (p2 = powof2 ((unsigned long)
- floatFromVal (right->operand.valOperand)))) {
+ !IS_FIXED (letype) &&
+ IS_UNSIGNED(letype) &&
+ (p2 = powof2 ((TYPE_UDWORD)
+ floatFromVal (right->operand.valOperand)))) {
ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
}
else
{
- ic = newiCode ('/', left, right); /* normal division */
+ ic = newiCode ('/', left, right); /* normal division */
/* if the size left or right > 1 then support routine */
if (getSize (ltype) > 1 || getSize (rtype) > 1)
- ic->supportRtn = 1;
+ ic->supportRtn = 1;
}
IC_RESULT (ic) = newiTempOperand (resType, 0);
/*-----------------------------------------------------------------*/
/* geniCodeModulus - gen intermediate code for modulus */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeModulus (operand * left, operand * right)
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
sym_link *resType;
/* if they are both literal then we know the result */
if (IS_LITERAL (letype) && IS_LITERAL (retype))
return operandFromValue (valMod (left->operand.valOperand,
- right->operand.valOperand));
+ right->operand.valOperand));
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, resultType, '%');
/* now they are the same size */
ic = newiCode ('%', left, right);
if (IS_LITERAL (letype) && IS_LITERAL (retype))
{
result = operandFromValue (valMinus (left->operand.valOperand,
- right->operand.valOperand));
+ right->operand.valOperand));
goto subtractExit;
}
// should we really do this? is this ANSI?
return geniCodeDivision (result,
- operandFromLit (getSize (ltype->next)));
+ operandFromLit (getSize (ltype->next)),
+ FALSE);
}
/*-----------------------------------------------------------------*/
/* geniCodeSubtract - generates code for subtraction */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeSubtract (operand * left, operand * right)
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int isarray = 0;
if (IS_LITERAL (letype) && IS_LITERAL (retype)
&& left->isLiteral && right->isLiteral)
return operandFromValue (valMinus (left->operand.valOperand,
- right->operand.valOperand));
+ right->operand.valOperand));
/* if left is an array or pointer */
if (IS_PTR (ltype) || IS_ARRAY (ltype))
{
isarray = left->isaddr;
right = geniCodeMultiply (right,
- operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+ operandFromLit (getSize (ltype->next)),
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
}
else
- { /* make them the same size */
- resType = usualBinaryConversions (&left, &right);
+ { /* make them the same size */
+ resType = usualBinaryConversions (&left, &right, resultType, '-');
}
ic = newiCode ('-', left, right);
IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
/* if left or right is a float */
- if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+ if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+ || IS_FIXED (ltype) || IS_FIXED (rtype))
ic->supportRtn = 1;
ADDTOCHAIN (ic);
/*-----------------------------------------------------------------*/
/* geniCodeAdd - generates iCode for addition */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeAdd (operand * left, operand * right, int lvl)
+static operand *
+geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
{
iCode *ic;
sym_link *resType;
operand *size;
int isarray = 0;
+ bool indexUnsigned;
LRTYPE;
-#if 0
- /* if left is an array then array access */
- if (IS_ARRAY (ltype))
- return geniCodeArray (left, right,lvl);
-#endif
-
/* if the right side is LITERAL zero */
/* return the left side */
- if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
+ if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
return left;
/* if left is literal zero return right */
- if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
+ if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
return right;
/* if left is a pointer then size */
{
isarray = left->isaddr;
// there is no need to multiply with 1
- if (getSize(ltype->next)!=1) {
- size = operandFromLit (getSize (ltype->next));
- right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
- }
+ if (getSize (ltype->next) != 1)
+ {
+ size = operandFromLit (getSize (ltype->next));
+ SPEC_USIGN (getSpec (operandType (size))) = 1;
+ indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+ right = geniCodeMultiply (right,
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
+ /* Even if right is a 'unsigned char',
+ the result will be a 'signed int' due to the promotion rules.
+ It doesn't make sense when accessing arrays, so let's fix it here: */
+ if (indexUnsigned)
+ SPEC_USIGN (getSpec (operandType (right))) = 1;
+ }
resType = copyLinkChain (ltype);
}
else
{ // make them the same size
- resType = usualBinaryConversions (&left, &right);
+ resType = usualBinaryConversions (&left, &right, resultType, '+');
}
/* if they are both literals then we know */
if (IS_LITERAL (letype) && IS_LITERAL (retype)
&& left->isLiteral && right->isLiteral)
- return operandFromValue (valPlus (valFromType (letype),
- valFromType (retype)));
+ return operandFromValue (valPlus (valFromType (ltype),
+ valFromType (rtype)));
ic = newiCode ('+', left, right);
/* if left or right is a float then support
routine */
- if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+ if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+ || IS_FIXED (ltype) || IS_FIXED (rtype))
ic->supportRtn = 1;
ADDTOCHAIN (ic);
}
/*-----------------------------------------------------------------*/
-/* aggrToPtr - changes an aggregate to pointer to an aggregate */
+/* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
/*-----------------------------------------------------------------*/
sym_link *
aggrToPtr (sym_link * type, bool force)
sym_link *etype;
sym_link *ptype;
-
if (IS_PTR (type) && !force)
return type;
ptype->next = type;
-#ifdef JWK
- /* if the output class is code */
- if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
- DCL_PTR_CONST (ptype) = port->mem.code_ro;
-
- /* if the variable was declared a constant */
- /* then the pointer points to a constant */
- if (IS_CONSTANT (etype))
- DCL_PTR_CONST (ptype) = 1;
-
- /* the variable was volatile then pointer to volatile */
- if (IS_VOLATILE (etype))
- DCL_PTR_VOLATILE (ptype) = 1;
-#else
+ /* set the pointer depending on the storage class */
DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
-#endif
-
return ptype;
}
+/*------------------------------------------------------------------*/
+/* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
+/*------------------------------------------------------------------*/
+int
+aggrToPtrDclType (sym_link * type, bool force)
+{
+ if (IS_PTR (type) && !force)
+ return DCL_TYPE (type);
+
+ /* return the pointer depending on the storage class */
+ return PTR_TYPE (SPEC_OCLS (getSpec (type)));
+}
+
/*-----------------------------------------------------------------*/
/* geniCodeArray2Ptr - array to pointer */
/*-----------------------------------------------------------------*/
-operand *
+static operand *
geniCodeArray2Ptr (operand * op)
{
sym_link *optype = operandType (op);
sym_link *opetype = getSpec (optype);
-#ifdef JWK
/* set the pointer depending on the storage class */
- if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
- DCL_PTR_CONST (optype) = port->mem.code_ro;
-
- /* if the variable was declared a constant */
- /* then the pointer points to a constant */
- if (IS_CONSTANT (opetype))
- DCL_PTR_CONST (optype) = 1;
-
- /* the variable was volatile then pointer to volatile */
- if (IS_VOLATILE (opetype))
- DCL_PTR_VOLATILE (optype) = 1;
-#else
DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
-#endif
op->isaddr = 0;
return op;
/*-----------------------------------------------------------------*/
/* geniCodeArray - array access */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeArray (operand * left, operand * right,int lvl)
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
{
iCode *ic;
+ operand *size;
sym_link *ltype = operandType (left);
+ bool indexUnsigned;
if (IS_PTR (ltype))
{
if (IS_PTR (ltype->next) && left->isaddr)
- {
- left = geniCodeRValue (left, FALSE);
- }
- return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
+ {
+ left = geniCodeRValue (left, FALSE);
+ }
+
+ return geniCodeDerefPtr (geniCodeAdd (left,
+ right,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR,
+ lvl),
+ lvl);
}
-
+ size = operandFromLit (getSize (ltype->next));
+ SPEC_USIGN (getSpec (operandType (size))) = 1;
+ indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
right = geniCodeMultiply (right,
- operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
-
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
+ /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
+ It doesn't make sense when accessing arrays, so let's fix it here: */
+ if (indexUnsigned)
+ SPEC_USIGN (getSpec (operandType (right))) = 1;
/* we can check for limits here */
+ /* already done in SDCCast.c
if (isOperandLiteral (right) &&
IS_ARRAY (ltype) &&
DCL_ELEM (ltype) &&
(operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
{
- werror (E_ARRAY_BOUND);
- right = operandFromLit (0);
+ werror (W_IDX_OUT_OF_BOUNDS,
+ (int) operandLitValue (right) / getSize (ltype->next),
+ DCL_ELEM (ltype));
}
+ */
ic = newiCode ('+', left, right);
IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
- !IS_AGGREGATE (ltype->next) &&
- !IS_PTR (ltype->next))
- ? ltype : ltype->next), 0);
+ !IS_AGGREGATE (ltype->next) &&
+ !IS_PTR (ltype->next))
+ ? ltype : ltype->next), 0);
- IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
+ if (!IS_AGGREGATE (ltype->next))
+ {
+ IC_RESULT (ic)->isaddr = 1;
+ IC_RESULT (ic)->aggr2ptr = 1;
+ }
ADDTOCHAIN (ic);
+
return IC_RESULT (ic);
}
/*-----------------------------------------------------------------*/
-/* geniCodeStruct - generates intermediate code for structres */
+/* geniCodeStruct - generates intermediate code for structures */
/*-----------------------------------------------------------------*/
operand *
geniCodeStruct (operand * left, operand * right, bool islval)
sym_link *etype = getSpec (type);
sym_link *retype;
symbol *element = getStructElement (SPEC_STRUCT (etype),
- right->operand.symOperand);
+ right->operand.symOperand);
wassert(IS_SYMOP(right));
-
+
/* add the offset */
ic = newiCode ('+', left, operandFromLit (element->offset));
SPEC_SCLS (retype) = SPEC_SCLS (etype);
SPEC_OCLS (retype) = SPEC_OCLS (etype);
SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
+ SPEC_CONST (retype) |= SPEC_CONST (etype);
if (IS_PTR (element->type))
setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
-
ADDTOCHAIN (ic);
return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
}
sym_link *optype = operandType (op);
operand *result;
operand *rv = (IS_ITEMP (op) ?
- geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
- op);
+ geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+ op);
sym_link *rvtype = operandType (rv);
int size = 0;
if (IS_ITEMP (rv))
OP_SYMBOL(rv)->noSpilLoc = 1;
- geniCodeAssign (rOp, rv, 0);
+ geniCodeAssign (rOp, rv, 0, 0);
size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
+ if (size == 0)
+ werror(W_SIZEOF_VOID);
if (IS_FLOAT (rvtype))
ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
+ else
+ if (IS_FIXED16X16 (rvtype))
+ ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
else
ic = newiCode ('+', rv, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
ADDTOCHAIN (ic);
- geniCodeAssign (op, result, 0);
+ geniCodeAssign (op, result, 0, 0);
return rOp;
/* geniCodePreInc - generate code for preIncrement */
/*-----------------------------------------------------------------*/
operand *
-geniCodePreInc (operand * op)
+geniCodePreInc (operand * op, bool lvalue)
{
iCode *ic;
sym_link *optype = operandType (op);
operand *rop = (IS_ITEMP (op) ?
- geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
- op);
+ geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+ op);
sym_link *roptype = operandType (rop);
operand *result;
int size = 0;
return op;
}
-
size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
+ if (size == 0)
+ werror(W_SIZEOF_VOID);
if (IS_FLOAT (roptype))
ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
+ else
+ if (IS_FIXED16X16 (roptype))
+ ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
else
ic = newiCode ('+', rop, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
-
- return geniCodeAssign (op, result, 0);
+ (void) geniCodeAssign (op, result, 0, 0);
+ if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
+ return op;
+ else
+ return result;
}
/*-----------------------------------------------------------------*/
sym_link *optype = operandType (op);
operand *result;
operand *rv = (IS_ITEMP (op) ?
- geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
- op);
+ geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+ op);
sym_link *rvtype = operandType (rv);
int size = 0;
if (IS_ITEMP (rv))
OP_SYMBOL(rv)->noSpilLoc = 1;
- geniCodeAssign (rOp, rv, 0);
+ geniCodeAssign (rOp, rv, 0, 0);
size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
+ if (size == 0)
+ werror(W_SIZEOF_VOID);
if (IS_FLOAT (rvtype))
ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
+ else
+ if (IS_FIXED16X16 (rvtype))
+ ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
else
ic = newiCode ('-', rv, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
ADDTOCHAIN (ic);
- geniCodeAssign (op, result, 0);
+ geniCodeAssign (op, result, 0, 0);
return rOp;
/* geniCodePreDec - generate code for pre decrement */
/*-----------------------------------------------------------------*/
operand *
-geniCodePreDec (operand * op)
+geniCodePreDec (operand * op, bool lvalue)
{
iCode *ic;
sym_link *optype = operandType (op);
operand *rop = (IS_ITEMP (op) ?
- geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
- op);
+ geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+ op);
sym_link *roptype = operandType (rop);
operand *result;
int size = 0;
return op;
}
-
size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
+ if (size == 0)
+ werror(W_SIZEOF_VOID);
if (IS_FLOAT (roptype))
ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
+ else
+ if (IS_FIXED16X16 (roptype))
+ ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
else
ic = newiCode ('-', rop, operandFromLit (size));
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
-
- return geniCodeAssign (op, result, 0);
+ (void) geniCodeAssign (op, result, 0, 0);
+ if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
+ return op;
+ else
+ return result;
}
/*-----------------------------------------------------------------*/
operand *
geniCodeBitwise (operand * left, operand * right,
- int oper, sym_link * resType)
+ int oper, sym_link * resType)
{
iCode *ic;
sym_link *optype = operandType (op);
sym_link *opetype = getSpec (optype);
+ if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
/* lvalue check already done in decorateType */
/* this must be a lvalue */
/* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
p = newLink (DECLARATOR);
-#ifdef JWK
/* set the pointer depending on the storage class */
- if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
- DCL_PTR_CONST (p) = port->mem.code_ro;
-
- /* make sure we preserve the const & volatile */
- if (IS_CONSTANT (opetype))
- DCL_PTR_CONST (p) = 1;
-
- if (IS_VOLATILE (opetype))
- DCL_PTR_VOLATILE (p) = 1;
-#else
DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
-#endif
-
p->next = copyLinkChain (optype);
/*-----------------------------------------------------------------*/
/* setOClass - sets the output class depending on the pointer type */
/*-----------------------------------------------------------------*/
-void
+void
setOClass (sym_link * ptr, sym_link * spec)
{
switch (DCL_TYPE (ptr))
sym_link *rtype, *retype;
sym_link *optype = operandType (op);
- /* if this is a pointer then generate the rvalue */
- if (IS_PTR (optype))
+ // if this is an array then array access
+ if (IS_ARRAY (optype)) {
+ // don't worry, this will be optimized out later
+ return geniCodeArray (op, operandFromLit (0), lvl);
+ }
+
+ // just in case someone screws up
+ wassert (IS_PTR (optype));
+
+ if (IS_TRUE_SYMOP (op))
{
- if (IS_TRUE_SYMOP (op))
- {
- op->isaddr = 1;
- op = geniCodeRValue (op, TRUE);
- }
- else
- op = geniCodeRValue (op, TRUE);
+ op->isaddr = 1;
+ op = geniCodeRValue (op, TRUE);
}
/* now get rid of the pointer part */
else
{
retype = getSpec (rtype = copyLinkChain (optype->next));
+ /* outputclass needs 2b updated */
+ setOClass (optype, retype);
}
- /* if this is a pointer then outputclass needs 2b updated */
- if (IS_PTR (optype))
- setOClass (optype, retype);
-
op->isGptr = IS_GENPTR (optype);
- /* if the pointer was declared as a constant */
- /* then we cannot allow assignment to the derefed */
- if (IS_PTR_CONST (optype))
- SPEC_CONST (retype) = 1;
-
op->isaddr = (IS_PTR (rtype) ||
- IS_STRUCT (rtype) ||
- IS_INT (rtype) ||
- IS_CHAR (rtype) ||
- IS_FLOAT (rtype));
+ IS_STRUCT (rtype) ||
+ IS_INT (rtype) ||
+ IS_CHAR (rtype) ||
+ IS_FLOAT (rtype) ||
+ IS_FIXED (rtype));
if (!isLvaluereq(lvl))
op = geniCodeRValue (op, TRUE);
/* geniCodeLeftShift - gen i code for left shift */
/*-----------------------------------------------------------------*/
operand *
-geniCodeLeftShift (operand * left, operand * right)
+geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
+ sym_link *resType;
ic = newiCode (LEFT_OP, left, right);
- IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+
+ resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
+ IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
/*-----------------------------------------------------------------*/
/* geniCodeLogic- logic code */
/*-----------------------------------------------------------------*/
-operand *
+static operand *
geniCodeLogic (operand * left, operand * right, int op)
{
iCode *ic;
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
- checkConstantRange(ltype,
- OP_VALUE(right), "compare operation", 1);
+ checkConstantRange(ltype,
+ OP_VALUE(right), "compare operation", 1);
+ }
+
+ /* if one operand is a pointer and the other is a literal generic void pointer,
+ change the type of the literal generic void pointer to match the other pointer */
+ if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
+ && IS_PTR (rtype) && !IS_GENPTR(rtype))
+ {
+ /* find left's definition */
+ ic = (iCode *) setFirstItem (iCodeChain);
+ while (ic)
+ {
+ if (((ic->op == CAST) || (ic->op == '='))
+ && isOperandEqual(left, IC_RESULT (ic)))
+ break;
+ else
+ ic = setNextItem (iCodeChain);
+ }
+ /* if casting literal to generic pointer, then cast to rtype instead */
+ if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
+ {
+ left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
+ ltype = operandType(left);
+ }
+ }
+ if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
+ && IS_PTR (ltype) && !IS_GENPTR(ltype))
+ {
+ /* find right's definition */
+ ic = (iCode *) setFirstItem (iCodeChain);
+ while (ic)
+ {
+ if (((ic->op == CAST) || (ic->op == '='))
+ && isOperandEqual(right, IC_RESULT (ic)))
+ break;
+ else
+ ic = setNextItem (iCodeChain);
+ }
+ /* if casting literal to generic pointer, then cast to rtype instead */
+ if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
+ {
+ right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
+ rtype = operandType(right);
+ }
}
- ctype = usualBinaryConversions (&left, &right);
+ ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
op != NE_OP &&
op != AND_OP &&
op != OR_OP)
+ ic->supportRtn = 1;
+
+ /* if comparing a fixed type use support functions */
+ if (IS_FIXED(ctype))
ic->supportRtn = 1;
ADDTOCHAIN (ic);
}
/*-----------------------------------------------------------------*/
-/* geniCodeUnary - for a a generic unary operation */
+/* geniCodeLogicAndOr - && || operations */
+/*-----------------------------------------------------------------*/
+static operand *
+geniCodeLogicAndOr (ast *tree, int lvl)
+{
+ iCode *ic;
+ sym_link *type;
+ symbol *falseLabel = newiTempLabel (NULL);
+ symbol *trueLabel = newiTempLabel (NULL);
+ symbol *exitLabel = newiTempLabel (NULL);
+ operand *op, *result, *condition;
+
+ /* AND_OP and OR_OP are no longer generated because of bug-905492.
+ They can be reenabled by executing the following block. If you find
+ a decent optimization you could start right here:
+ */
+#if 0
+ if (0)
+ {
+ operand *leftOp, *rightOp;
+
+ leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
+ rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
+
+ return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+ }
+#endif
+
+ /* generate two IFX for the '&&' or '||' op */
+
+ /* evaluate left operand */
+ condition = ast2iCode (tree->left, lvl + 1);
+ op = geniCodeRValue (condition, FALSE);
+
+ /* test left operand */
+ if (tree->opval.op == AND_OP)
+ ic = newiCodeCondition (op, NULL, falseLabel);
+ else /* OR_OP */
+ ic = newiCodeCondition (op, trueLabel, NULL);
+ ADDTOCHAIN (ic);
+
+ /* evaluate right operand */
+ condition = ast2iCode (tree->right, lvl + 1);
+ op = geniCodeRValue (condition, FALSE);
+
+ /* test right operand */
+ ic = newiCodeCondition (op, trueLabel, NULL);
+ ADDTOCHAIN (ic);
+
+ /* store 0 or 1 in result */
+ type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
+ result = newiTempOperand (type, 1);
+
+ geniCodeLabel (falseLabel);
+ geniCodeAssign (result, operandFromLit (0), 0, 0);
+ /* generate an unconditional goto */
+ geniCodeGoto (exitLabel);
+
+ geniCodeLabel (trueLabel);
+ geniCodeAssign (result, operandFromLit (1), 0, 0);
+
+ geniCodeLabel (exitLabel);
+
+ return result;
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeUnary - for a generic unary operation */
/*-----------------------------------------------------------------*/
operand *
geniCodeUnary (operand * op, int oper)
return IC_RESULT (ic);
}
+/*-----------------------------------------------------------------*/
+/* geniCodeBinary - for a generic binary operation */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeBinary (operand * left, operand * right, int oper)
+{
+ iCode *ic = newiCode (oper, left, right);
+
+ IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
/*-----------------------------------------------------------------*/
/* geniCodeConditional - geniCode for '?' ':' operation */
/*-----------------------------------------------------------------*/
operand *true, *false, *result;
ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
- NULL, falseLabel);
+ NULL, falseLabel);
ADDTOCHAIN (ic);
true = ast2iCode (tree->right->left,lvl+1);
/* move the value to a new Operand */
result = newiTempOperand (tree->right->ftype, 0);
- geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
+ geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
/* generate an unconditional goto */
geniCodeGoto (exitLabel);
geniCodeLabel (falseLabel);
false = ast2iCode (tree->right->right,lvl+1);
- geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
+ geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
/* create the exit label */
geniCodeLabel (exitLabel);
/* geniCodeAssign - generate code for assignment */
/*-----------------------------------------------------------------*/
operand *
-geniCodeAssign (operand * left, operand * right, int nosupdate)
+geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
{
iCode *ic;
sym_link *ltype = operandType (left);
sym_link *rtype = operandType (right);
- if (!left->isaddr && !IS_ITEMP (left))
+ if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
{
werror (E_LVALUE_REQUIRED, "assignment");
return left;
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
{
- checkConstantRange(ltype,
- OP_VALUE(right), "= operation", 0);
+ checkConstantRange(ltype,
+ OP_VALUE(right), "= operation", 0);
}
/* if the left & right type don't exactly match */
compareType (ltype, rtype) <= 0)
{
if (compareType (ltype->next, rtype) < 0)
- right = geniCodeCast (ltype->next, right, TRUE);
+ right = geniCodeCast (ltype->next, right, TRUE);
}
else if (compareType (ltype, rtype) < 0)
right = geniCodeCast (ltype, right, TRUE);
- /* if left is a true symbol & ! volatile
+ /* If left is a true symbol & ! volatile
create an assignment to temporary for
the right & then assign this temporary
- to the symbol this is SSA . isn't it simple
- and folks have published mountains of paper on it */
+ to the symbol. This is SSA (static single
+ assignment). Isn't it simple and folks have
+ published mountains of paper on it */
if (IS_TRUE_SYMOP (left) &&
!isOperandVolatile (left, FALSE) &&
isOperandGlobal (left))
symbol *sym = NULL;
if (IS_TRUE_SYMOP (right))
- sym = OP_SYMBOL (right);
+ sym = OP_SYMBOL (right);
ic = newiCode ('=', NULL, right);
IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
SPIL_LOC (right) = sym;
return left;
}
+/*-----------------------------------------------------------------*/
+/* geniCodeDummyRead - generate code for dummy read */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeDummyRead (operand * op)
+{
+ iCode *ic;
+ sym_link *type = operandType (op);
+
+ if (!IS_VOLATILE(type))
+ return;
+
+ ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
+ ADDTOCHAIN (ic);
+
+ ic->nosupdate = 1;
+}
+
/*-----------------------------------------------------------------*/
/* geniCodeSEParms - generate code for side effecting fcalls */
/*-----------------------------------------------------------------*/
-static void
+static void
geniCodeSEParms (ast * parms,int lvl)
{
if (!parms)
IS_ADDRESS_OF_OP (parms->right))
parms->right->left->lvalue = 1;
- parms->opval.oprnd =
+ parms->opval.oprnd =
geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
-
+
parms->type = EX_OPERAND;
AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
- SPEC_ARGREG(parms->ftype);
+ SPEC_ARGREG(parms->ftype);
}
/*-----------------------------------------------------------------*/
/* geniCodeParms - generates parameters */
/*-----------------------------------------------------------------*/
value *
-geniCodeParms (ast * parms, value *argVals, int *stack,
- sym_link * fetype, symbol * func,int lvl)
+geniCodeParms (ast * parms, value *argVals, int *stack,
+ sym_link * ftype, int lvl)
{
iCode *ic;
operand *pval;
if (argVals==NULL) {
// first argument
- argVals=FUNC_ARGS(func->type);
+ argVals = FUNC_ARGS (ftype);
}
/* if this is a param node then do the left & right */
if (parms->type == EX_OP && parms->opval.op == PARAM)
{
- argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
- argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+ argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+ argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
return argVals;
}
/* hack don't like this but too lazy to think of
something better */
if (IS_ADDRESS_OF_OP (parms))
- parms->left->lvalue = 1;
+ parms->left->lvalue = 1;
if (IS_CAST_OP (parms) &&
- IS_PTR (parms->ftype) &&
- IS_ADDRESS_OF_OP (parms->right))
- parms->right->left->lvalue = 1;
+ IS_PTR (parms->ftype) &&
+ IS_ADDRESS_OF_OP (parms->right))
+ parms->right->left->lvalue = 1;
pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
}
/* if register parm then make it a send */
- if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
- IFFUNC_ISBUILTIN(func->type))
+ if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+ IFFUNC_ISBUILTIN(ftype))
{
ic = newiCode (SEND, pval, NULL);
ic->argreg = SPEC_ARGREG(parms->etype);
- ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+ ic->builtinSEND = FUNC_ISBUILTIN(ftype);
ADDTOCHAIN (ic);
}
else
{
/* now decide whether to push or assign */
- if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
- {
-
- /* assign */
- operand *top = operandFromSymbol (argVals->sym);
- /* clear useDef and other bitVectors */
- OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
- geniCodeAssign (top, pval, 1);
- }
+ if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
+ {
+
+ /* assign */
+ operand *top = operandFromSymbol (argVals->sym);
+ /* clear useDef and other bitVectors */
+ OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
+ geniCodeAssign (top, pval, 1, 0);
+ }
else
- {
- sym_link *p = operandType (pval);
- /* push */
- ic = newiCode (IPUSH, pval, NULL);
- ic->parmPush = 1;
- /* update the stack adjustment */
- *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
- ADDTOCHAIN (ic);
- }
+ {
+ sym_link *p = operandType (pval);
+ /* push */
+ ic = newiCode (IPUSH, pval, NULL);
+ ic->parmPush = 1;
+ /* update the stack adjustment */
+ *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
+ ADDTOCHAIN (ic);
+ }
}
argVals=argVals->next;
iCode *ic;
operand *result;
sym_link *type, *etype;
+ sym_link *ftype;
int stack = 0;
- if (!IS_FUNC(OP_SYMBOL(left)->type) &&
- !IS_CODEPTR(OP_SYMBOL(left)->type)) {
+ if (!IS_FUNC(OP_SYMBOL(left)->type) &&
+ !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
werror (E_FUNCTION_EXPECTED);
- return NULL;
+ return operandFromValue(valueFromLit(0));
}
/* take care of parameters with side-effecting
of overlaying function parameters */
geniCodeSEParms (parms,lvl);
+ ftype = operandType (left);
+ if (IS_FUNCPTR (ftype))
+ ftype = ftype->next;
+
/* first the parameters */
- geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+ geniCodeParms (parms, NULL, &stack, ftype, lvl);
/* now call : if symbol then pcall */
if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
ic = newiCode (CALL, left, NULL);
}
- type = copyLinkChain (operandType (left)->next);
+ type = copyLinkChain (ftype->next);
etype = getSpec (type);
SPEC_EXTR (etype) = 0;
IC_RESULT (ic) = result = newiTempOperand (type, 1);
/*-----------------------------------------------------------------*/
/* geniCodeReceive - generate intermediate code for "receive" */
/*-----------------------------------------------------------------*/
-static void
-geniCodeReceive (value * args)
+static void
+geniCodeReceive (value * args, operand * func)
{
+ unsigned char paramByteCounter = 0;
+
/* for all arguments that are passed in registers */
while (args)
{
- int first = 1;
if (IS_REGPARM (args->etype))
- {
- operand *opr = operandFromValue (args);
- operand *opl;
- symbol *sym = OP_SYMBOL (opr);
- iCode *ic;
-
- /* we will use it after all optimizations
- and before liveRange calculation */
- if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
- {
-
- if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
- options.stackAuto == 0 &&
- (!(options.model == MODEL_FLAT24)) )
- {
- }
- else
- {
- opl = newiTempOperand (args->type, 0);
- sym->reqv = opl;
- sym->reqv->key = sym->key;
- OP_SYMBOL (sym->reqv)->key = sym->key;
- OP_SYMBOL (sym->reqv)->isreqv = 1;
- OP_SYMBOL (sym->reqv)->islocal = 0;
- SPIL_LOC (sym->reqv) = sym;
- }
- }
-
- ic = newiCode (RECEIVE, NULL, NULL);
- ic->argreg = SPEC_ARGREG(args->etype);
- if (first) {
- currFunc->recvSize = getSize (sym->type);
- first = 0;
- }
- IC_RESULT (ic) = opr;
- ADDTOCHAIN (ic);
- }
+ {
+ operand *opr = operandFromValue (args);
+ operand *opl;
+ symbol *sym = OP_SYMBOL (opr);
+ iCode *ic;
+
+ /* we will use it after all optimizations
+ and before liveRange calculation */
+ if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
+ {
+
+ if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
+ options.stackAuto == 0 &&
+ (!(options.model == MODEL_FLAT24)) )
+ {
+ }
+ else
+ {
+ opl = newiTempOperand (args->type, 0);
+ sym->reqv = opl;
+ sym->reqv->key = sym->key;
+ OP_SYMBOL (sym->reqv)->key = sym->key;
+ OP_SYMBOL (sym->reqv)->isreqv = 1;
+ OP_SYMBOL (sym->reqv)->islocal = 0;
+ SPIL_LOC (sym->reqv) = sym;
+ }
+ }
+
+ ic = newiCode (RECEIVE, func, NULL);
+ ic->argreg = SPEC_ARGREG(args->etype);
+ if (ic->argreg == 1) {
+ currFunc->recvSize = getSize (sym->type);
+ }
+ IC_RESULT (ic) = opr;
+
+ /* misuse of parmBytes (normally used for functions)
+ * to save estimated stack position of this argument.
+ * Normally this should be zero for RECEIVE iCodes.
+ * No idea if this causes side effects on other ports. - dw
+ */
+ ic->parmBytes = paramByteCounter;
+
+ /* what stack position do we have? */
+ paramByteCounter += getSize (sym->type);
+
+ ADDTOCHAIN (ic);
+ }
args = args->next;
}
/*-----------------------------------------------------------------*/
/* geniCodeFunctionBody - create the function body */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeFunctionBody (ast * tree,int lvl)
{
iCode *ic;
/* create a proc icode */
ic = newiCode (FUNCTION, func, NULL);
lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
+ ic->tree = tree;
ADDTOCHAIN (ic);
/* for all parameters that are passed
on registers add a "receive" */
- geniCodeReceive (tree->values.args);
+ geniCodeReceive (tree->values.args, func);
/* generate code for the body */
ast2iCode (tree->right,lvl+1);
/* now generate the end proc */
ic = newiCode (ENDFUNCTION, func, NULL);
+ ic->tree = tree;
ADDTOCHAIN (ic);
return;
}
/*-----------------------------------------------------------------*/
/* geniCodeReturn - gen icode for 'return' statement */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeReturn (operand * op)
{
iCode *ic;
/*-----------------------------------------------------------------*/
/* geniCodeIfx - generates code for extended if statement */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeIfx (ast * tree,int lvl)
{
iCode *ic;
if (IS_LITERAL (cetype))
{
if (floatFromVal (condition->operand.valOperand))
- {
- if (tree->trueLabel)
- geniCodeGoto (tree->trueLabel);
- else
- assert (0);
- }
+ {
+ if (tree->trueLabel)
+ geniCodeGoto (tree->trueLabel);
+ else
+ assert (0);
+ }
else
- {
- if (tree->falseLabel)
- geniCodeGoto (tree->falseLabel);
- else
- assert (0);
- }
+ {
+ if (tree->falseLabel)
+ geniCodeGoto (tree->falseLabel);
+ else
+ assert (0);
+ }
goto exit;
}
if (tree->trueLabel)
{
ic = newiCodeCondition (condition,
- tree->trueLabel,
- NULL);
+ tree->trueLabel,
+ NULL);
ADDTOCHAIN (ic);
if (tree->falseLabel)
- geniCodeGoto (tree->falseLabel);
+ geniCodeGoto (tree->falseLabel);
}
else
{
ic = newiCodeCondition (condition,
- NULL,
- tree->falseLabel);
+ NULL,
+ tree->falseLabel);
ADDTOCHAIN (ic);
}
/*-----------------------------------------------------------------*/
/* geniCodeJumpTable - tries to create a jump table for switch */
/*-----------------------------------------------------------------*/
-int
+int
geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
{
- int min = 0, max = 0, t, cnt = 0;
+ int min, max, cnt = 1;
+ int i, t;
value *vch;
iCode *ic;
operand *boundary;
symbol *falseLabel;
set *labels = NULL;
+ int needRangeCheck = !optimize.noJTabBoundary
+ || tree->values.switchVals.swDefault;
+ sym_link *cetype = getSpec (operandType (cond));
+ int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
+ int sizeofMatchJump, sizeofJumpTable;
+ int sizeIndex;
if (!tree || !caseVals)
return 0;
/* the criteria for creating a jump table is */
/* all integer numbers between the maximum & minimum must */
/* be present , the maximum value should not exceed 255 */
- min = max = (int) floatFromVal (vch = caseVals);
- SNPRINTF (buffer, sizeof(buffer),
- "_case_%d_%d",
- tree->values.switchVals.swNum,
- min);
- addSet (&labels, newiTempLabel (buffer));
-
- /* if there is only one case value then no need */
- if (!(vch = vch->next))
- return 0;
+ /* If not all integer numbers are present the algorithm */
+ /* inserts jumps to the default label for the missing numbers */
+ /* and decides later whether it is worth it */
+ min = (int) floatFromVal (vch = caseVals);
- while (vch)
+ while (vch->next)
{
- if (((t = (int) floatFromVal (vch)) - max) != 1)
- return 0;
- SNPRINTF (buffer, sizeof(buffer),
- "_case_%d_%d",
- tree->values.switchVals.swNum,
- t);
- addSet (&labels, newiTempLabel (buffer));
- max = t;
cnt++;
vch = vch->next;
}
+ max = (int) floatFromVal (vch);
+
+ /* Exit if the range is too large to handle with a jump table. */
+ if (1 + max - min > port->jumptableCost.maxCount)
+ return 0;
+
+ switch (getSize (operandType (cond)))
+ {
+ case 1: sizeIndex = 0; break;
+ case 2: sizeIndex = 1; break;
+ case 4: sizeIndex = 2; break;
+ default: return 0;
+ }
+
+ /* Compute the size cost of the range check and subtraction. */
+ sizeofMinCost = 0;
+ sizeofZeroMinCost = 0;
+ sizeofMaxCost = 0;
+ if (needRangeCheck)
+ {
+ if (!(min==0 && IS_UNSIGNED (cetype)))
+ sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+ if (!IS_UNSIGNED (cetype))
+ sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+ sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+ }
+ if (min)
+ sizeofMinCost += port->jumptableCost.sizeofSubtract;
+
+ /* If the size cost of handling a non-zero minimum exceeds the */
+ /* cost of extending the range down to zero, then it might be */
+ /* better to extend the range to zero. */
+ if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
+ >= (min * port->jumptableCost.sizeofElement))
+ {
+ /* Only extend the jump table if it would still be manageable. */
+ if (1 + max <= port->jumptableCost.maxCount)
+ {
+ min = 0;
+ if (IS_UNSIGNED (cetype))
+ sizeofMinCost = 0;
+ else
+ sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+ }
+ }
+
+ /* Compute the total size cost of a jump table. */
+ sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
+ + port->jumptableCost.sizeofDispatch
+ + sizeofMinCost + sizeofMaxCost;
- /* if the number of case statements <= 2 then */
- /* it is not economical to create the jump table */
- /* since two compares are needed for boundary conditions */
- if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
+ /* Compute the total size cost of a match & jump sequence */
+ sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
+
+ /* If the size cost of the jump table is uneconomical then exit */
+ if (sizeofMatchJump < sizeofJumpTable)
return 0;
+ /* The jump table is preferable. */
+
+ /* First, a label for the default or missing cases. */
if (tree->values.switchVals.swDefault)
{
- SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+ SNPRINTF (buffer, sizeof(buffer),
+ "_default_%d",
+ tree->values.switchVals.swNum);
}
else
{
- SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+ SNPRINTF (buffer, sizeof(buffer),
+ "_swBrk_%d",
+ tree->values.switchVals.swNum);
}
-
-
falseLabel = newiTempLabel (buffer);
- /* so we can create a jumptable */
+ /* Build the list of labels for the jump table. */
+ vch = caseVals;
+ t = (int) floatFromVal (vch);
+ for (i=min; i<=max; i++)
+ {
+ if (vch && t==i)
+ {
+ /* Explicit case: make a new label for it. */
+ SNPRINTF (buffer, sizeof(buffer),
+ "_case_%d_%d",
+ tree->values.switchVals.swNum,
+ i);
+ addSet (&labels, newiTempLabel (buffer));
+ vch = vch->next;
+ if (vch)
+ t = (int) floatFromVal (vch);
+ }
+ else
+ {
+ /* Implicit case: use the default label. */
+ addSet (&labels, falseLabel);
+ }
+ }
+
/* first we rule out the boundary conditions */
/* if only optimization says so */
- if (!optimize.noJTabBoundary)
+ if (needRangeCheck)
{
sym_link *cetype = getSpec (operandType (cond));
/* no need to check the lower bound if
the condition is unsigned & minimum value is zero */
- if (!(min == 0 && SPEC_USIGN (cetype)))
- {
- boundary = geniCodeLogic (cond, operandFromLit (min), '<');
- ic = newiCodeCondition (boundary, falseLabel, NULL);
- ADDTOCHAIN (ic);
- }
+ if (!(min == 0 && IS_UNSIGNED (cetype)))
+ {
+ boundary = geniCodeLogic (cond, operandFromLit (min), '<');
+ ic = newiCodeCondition (boundary, falseLabel, NULL);
+ ADDTOCHAIN (ic);
+ }
/* now for upper bounds */
boundary = geniCodeLogic (cond, operandFromLit (max), '>');
/* if the min is not zero then we no make it zero */
if (min)
{
- cond = geniCodeSubtract (cond, operandFromLit (min));
- setOperandType (cond, UCHARTYPE);
+ cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
+ if (!IS_LITERAL(getSpec(operandType(cond))))
+ setOperandType (cond, UCHARTYPE);
}
/* now create the jumptable */
/*-----------------------------------------------------------------*/
/* geniCodeSwitch - changes a switch to a if statement */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeSwitch (ast * tree,int lvl)
{
iCode *ic;
value *caseVals = tree->values.switchVals.swVals;
symbol *trueLabel, *falseLabel;
+ /* If the condition is a literal, then just jump to the */
+ /* appropriate case label. */
+ if (IS_LITERAL(getSpec(operandType(cond))))
+ {
+ int switchVal, caseVal;
+
+ switchVal = (int) floatFromVal (cond->operand.valOperand);
+ while (caseVals)
+ {
+ caseVal = (int) floatFromVal (caseVals);
+ if (caseVal == switchVal)
+ {
+ SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
+ tree->values.switchVals.swNum, caseVal);
+ trueLabel = newiTempLabel (buffer);
+ geniCodeGoto (trueLabel);
+ goto jumpTable;
+ }
+ caseVals = caseVals->next;
+ }
+ goto defaultOrBreak;
+ }
+
+ /* If cond is volatile, it might change while we are trying to */
+ /* find the matching case. To avoid this possibility, make a */
+ /* non-volatile copy to use instead. */
+ if (IS_OP_VOLATILE (cond))
+ {
+ operand * newcond;
+ iCode * ic;
+
+ newcond = newiTempOperand (operandType (cond), TRUE);
+ newcond->isvolatile = 0;
+ ic = newiCode ('=', NULL, cond);
+ IC_RESULT (ic) = newcond;
+ ADDTOCHAIN (ic);
+ cond = newcond;
+ }
+
/* if we can make this a jump table */
if (geniCodeJumpTable (cond, caseVals, tree))
- goto jumpTable; /* no need for the comparison */
+ goto jumpTable; /* no need for the comparison */
/* for the cases defined do */
while (caseVals)
{
operand *compare = geniCodeLogic (cond,
- operandFromValue (caseVals),
- EQ_OP);
+ operandFromValue (caseVals),
+ EQ_OP);
SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
- tree->values.switchVals.swNum,
- (int) floatFromVal (caseVals));
+ tree->values.switchVals.swNum,
+ (int) floatFromVal (caseVals));
trueLabel = newiTempLabel (buffer);
ic = newiCodeCondition (compare, trueLabel, NULL);
}
-
+defaultOrBreak:
/* if default is present then goto break else break */
if (tree->values.switchVals.swDefault)
{
- SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+ SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
}
else
{
- SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+ SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
}
falseLabel = newiTempLabel (buffer);
/*-----------------------------------------------------------------*/
/* geniCodeInline - intermediate code for inline assembler */
/*-----------------------------------------------------------------*/
-static void
+static void
geniCodeInline (ast * tree)
{
iCode *ic;
/*-----------------------------------------------------------------*/
/* geniCodeArrayInit - intermediate code for array initializer */
/*-----------------------------------------------------------------*/
-static void
+static void
geniCodeArrayInit (ast * tree, operand *array)
{
iCode *ic;
ADDTOCHAIN (ic);
}
+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeCritical (ast *tree, int lvl)
+{
+ iCode *ic;
+ operand *op = NULL;
+ sym_link *type;
+
+ if (!options.stackAuto)
+ {
+ type = newLink(SPECIFIER);
+ SPEC_VOLATILE(type) = 1;
+ SPEC_NOUN(type) = V_BIT;
+ SPEC_SCLS(type) = S_BIT;
+ SPEC_BLEN(type) = 1;
+ SPEC_BSTR(type) = 0;
+ op = newiTempOperand(type, 1);
+ }
+
+ /* If op is NULL, the original interrupt state will saved on */
+ /* the stack. Otherwise, it will be saved in op. */
+
+ /* Generate a save of the current interrupt state & disable */
+ ic = newiCode (CRITICAL, NULL, NULL);
+ IC_RESULT (ic) = op;
+ ADDTOCHAIN (ic);
+
+ /* Generate the critical code sequence */
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+
+ /* Generate a restore of the original interrupt state */
+ ic = newiCode (ENDCRITICAL, NULL, op);
+ ADDTOCHAIN (ic);
+}
+
/*-----------------------------------------------------------------*/
/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
/* particular case. Ie : assigning or dereferencing array or ptr */
if(lpItem) Safe_free(lpItem);
}
/*-----------------------------------------------------------------*/
-/* clearLvaluereq - clear lvalreq flag */
+/* clearLvaluereq - clear lvalreq flag */
/*-----------------------------------------------------------------*/
void clearLvaluereq()
{
if(lpItem) lpItem->req = 0;
}
/*-----------------------------------------------------------------*/
-/* getLvaluereq - get the last lvalreq level */
+/* getLvaluereq - get the last lvalreq level */
/*-----------------------------------------------------------------*/
int getLvaluereqLvl()
{
return 0;
}
/*-----------------------------------------------------------------*/
-/* isLvaluereq - is lvalreq valid for this level ? */
+/* isLvaluereq - is lvalreq valid for this level ? */
/*-----------------------------------------------------------------*/
int isLvaluereq(int lvl)
{
block = tree->block;
if (tree->level)
scopeLevel = tree->level;
+ if (tree->seqPoint)
+ seqPoint = tree->seqPoint;
if (tree->type == EX_VALUE)
return operandFromValue (tree->opval.val);
(tree->opval.op == NULLOP ||
tree->opval.op == BLOCK))
{
- ast2iCode (tree->left,lvl+1);
- ast2iCode (tree->right,lvl+1);
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+ if (tree->right && tree->right->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
+ else
+ ast2iCode (tree->right,lvl+1);
return NULL;
}
tree->opval.op != '?' &&
tree->opval.op != CALL &&
tree->opval.op != IFX &&
+ tree->opval.op != AND_OP &&
+ tree->opval.op != OR_OP &&
tree->opval.op != LABEL &&
tree->opval.op != GOTO &&
tree->opval.op != SWITCH &&
tree->opval.op != FUNCTION &&
- tree->opval.op != INLINEASM)
+ tree->opval.op != INLINEASM &&
+ tree->opval.op != CRITICAL)
{
if (IS_ASSIGN_OP (tree->opval.op) ||
left = operandFromAst (tree->left,lvl);
delLvaluereq();
if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
- left = geniCodeRValue (left, TRUE);
+ left = geniCodeRValue (left, TRUE);
}
else
{
- left = operandFromAst (tree->left,lvl);
+ left = operandFromAst (tree->left,lvl);
}
if (tree->opval.op == INC_OP ||
- tree->opval.op == DEC_OP)
+ tree->opval.op == DEC_OP)
{
- addLvaluereq(lvl);
- right = operandFromAst (tree->right,lvl);
- delLvaluereq();
+ addLvaluereq(lvl);
+ right = operandFromAst (tree->right,lvl);
+ delLvaluereq();
}
else
{
- right = operandFromAst (tree->right,lvl);
+ right = operandFromAst (tree->right,lvl);
}
}
switch (tree->opval.op)
{
- case '[': /* array operation */
+ case '[': /* array operation */
{
- //sym_link *ltype = operandType (left);
- //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
- left = geniCodeRValue (left, FALSE);
- right = geniCodeRValue (right, TRUE);
+ //sym_link *ltype = operandType (left);
+ //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+ left = geniCodeRValue (left, FALSE);
+ right = geniCodeRValue (right, TRUE);
}
return geniCodeArray (left, right,lvl);
- case '.': /* structure dereference */
+ case '.': /* structure dereference */
if (IS_PTR (operandType (left)))
- left = geniCodeRValue (left, TRUE);
+ left = geniCodeRValue (left, TRUE);
else
- left = geniCodeRValue (left, FALSE);
+ left = geniCodeRValue (left, FALSE);
return geniCodeStruct (left, right, tree->lvalue);
- case PTR_OP: /* structure pointer dereference */
+ case PTR_OP: /* structure pointer dereference */
{
- sym_link *pType;
- pType = operandType (left);
- left = geniCodeRValue (left, TRUE);
+ sym_link *pType;
+ pType = operandType (left);
+ left = geniCodeRValue (left, TRUE);
- setOClass (pType, getSpec (operandType (left)));
+ setOClass (pType, getSpec (operandType (left)));
}
return geniCodeStruct (left, right, tree->lvalue);
- case INC_OP: /* increment operator */
+ case INC_OP: /* increment operator */
if (left)
- return geniCodePostInc (left);
+ return geniCodePostInc (left);
else
- return geniCodePreInc (right);
+ return geniCodePreInc (right, tree->lvalue);
- case DEC_OP: /* decrement operator */
+ case DEC_OP: /* decrement operator */
if (left)
- return geniCodePostDec (left);
+ return geniCodePostDec (left);
else
- return geniCodePreDec (right);
+ return geniCodePreDec (right, tree->lvalue);
- case '&': /* bitwise and or address of operator */
+ case '&': /* bitwise and or address of operator */
if (right)
- { /* this is a bitwise operator */
- left = geniCodeRValue (left, FALSE);
- right = geniCodeRValue (right, FALSE);
- return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
- }
+ { /* this is a bitwise operator */
+ left = geniCodeRValue (left, FALSE);
+ right = geniCodeRValue (right, FALSE);
+ return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
+ }
else
- return geniCodeAddressOf (left);
+ return geniCodeAddressOf (left);
- case '|': /* bitwise or & xor */
+ case '|': /* bitwise or & xor */
case '^':
return geniCodeBitwise (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),
- tree->opval.op,
- tree->ftype);
+ geniCodeRValue (right, FALSE),
+ tree->opval.op,
+ tree->ftype);
case '/':
return geniCodeDivision (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case '%':
return geniCodeModulus (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case '*':
if (right)
- return geniCodeMultiply (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
+ return geniCodeMultiply (geniCodeRValue (left, FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
else
- return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
+ return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
if (right)
- return geniCodeSubtract (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ return geniCodeSubtract (geniCodeRValue (left, FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
else
- return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
+ return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
case '+':
if (right)
- return geniCodeAdd (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),lvl);
+ return geniCodeAdd (geniCodeRValue (left, FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype),
+ lvl);
else
- return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
+ return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
case LEFT_OP:
return geniCodeLeftShift (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case RIGHT_OP:
return geniCodeRightShift (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE));
case CAST:
+#if 0 // this indeed needs a second thought
+ {
+ operand *op;
+
+ // let's keep this simple: get the rvalue we need
+ op=geniCodeRValue (right, FALSE);
+ // now cast it to whatever we want
+ op=geniCodeCast (operandType(left), op, FALSE);
+ // if this is going to be used as an lvalue, make it so
+ if (tree->lvalue) {
+ op->isaddr=1;
+ }
+ return op;
+ }
+#else // bug #604575, is it a bug ????
return geniCodeCast (operandType (left),
- geniCodeRValue (right, FALSE), FALSE);
+ geniCodeRValue (right, FALSE), FALSE);
+#endif
case '~':
- case '!':
case RRC:
case RLC:
+ case SWAP:
return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+ case '!':
case GETHBIT:
{
- operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
- setOperandType (op, UCHARTYPE);
- return op;
+ operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+ setOperandType (op, UCHARTYPE);
+ return op;
+ }
+ case GETABIT:
+ case GETBYTE:
+ case GETWORD:
+ {
+ operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
+ geniCodeRValue (right, FALSE),
+ tree->opval.op);
+ setOperandType (op, (tree->opval.op == GETWORD) ? UINTTYPE : UCHARTYPE);
+ return op;
}
+ case AND_OP:
+ case OR_OP:
+ return geniCodeLogicAndOr (tree, lvl);
case '>':
case '<':
case LE_OP:
case GE_OP:
case EQ_OP:
case NE_OP:
- case AND_OP:
- case OR_OP:
+ /* different compilers (even different gccs) evaluate
+ the two calls in a different order. to get the same
+ result on all machines we've to specify a clear sequence.
return geniCodeLogic (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),
- tree->opval.op);
+ geniCodeRValue (right, FALSE),
+ tree->opval.op);
+ */
+ {
+ operand *leftOp, *rightOp;
+
+ leftOp = geniCodeRValue (left , FALSE);
+ rightOp = geniCodeRValue (right, FALSE);
+
+ return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+ }
case '?':
return geniCodeConditional (tree,lvl);
case '=':
{
- sym_link *rtype = operandType (right);
- sym_link *ltype = operandType (left);
- if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && compareType (rtype->next, ltype) == 1)
- right = geniCodeRValue (right, TRUE);
- else
- right = geniCodeRValue (right, FALSE);
-
- geniCodeAssign (left, right, 0);
- return right;
+ sym_link *rtype = operandType (right);
+ sym_link *ltype = operandType (left);
+ if (IS_PTR (rtype) && IS_ITEMP (right)
+ && right->isaddr && compareType (rtype->next, ltype) == 1)
+ right = geniCodeRValue (right, TRUE);
+ else
+ right = geniCodeRValue (right, FALSE);
+
+ geniCodeAssign (left, right, 0, 1);
+ return right;
}
case MUL_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
- FALSE),
- geniCodeRValue (right, FALSE),FALSE), 0);
+ geniCodeAssign (left,
+ geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0, 1);
case DIV_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeDivision (geniCodeRValue (operandFromOperand (left),
- FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeAssign (left,
+ geniCodeDivision (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0, 1);
case MOD_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeModulus (geniCodeRValue (operandFromOperand (left),
- FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeAssign (left,
+ geniCodeModulus (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0, 1);
case ADD_ASSIGN:
{
- sym_link *rtype = operandType (right);
- sym_link *ltype = operandType (left);
- if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && compareType (rtype->next, ltype) == 1)
- right = geniCodeRValue (right, TRUE);
- else
- right = geniCodeRValue (right, FALSE);
-
-
- return geniCodeAssign (left,
- geniCodeAdd (geniCodeRValue (operandFromOperand (left),
- FALSE),
- right,lvl), 0);
+ sym_link *rtype = operandType (right);
+ sym_link *ltype = operandType (left);
+ if (IS_PTR (rtype) && IS_ITEMP (right)
+ && right->isaddr && compareType (rtype->next, ltype) == 1)
+ right = geniCodeRValue (right, TRUE);
+ else
+ right = geniCodeRValue (right, FALSE);
+
+
+ return geniCodeAssign (left,
+ geniCodeAdd (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ right,
+ getResultTypeFromType (tree->ftype),
+ lvl),
+ 0, 1);
}
case SUB_ASSIGN:
{
- sym_link *rtype = operandType (right);
- sym_link *ltype = operandType (left);
- if (IS_PTR (rtype) && IS_ITEMP (right)
- && right->isaddr && compareType (rtype->next, ltype) == 1)
- {
- right = geniCodeRValue (right, TRUE);
- }
- else
- {
- right = geniCodeRValue (right, FALSE);
- }
- return
- geniCodeAssign (left,
- geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
- FALSE),
- right), 0);
+ sym_link *rtype = operandType (right);
+ sym_link *ltype = operandType (left);
+ if (IS_PTR (rtype) && IS_ITEMP (right)
+ && right->isaddr && compareType (rtype->next, ltype) == 1)
+ {
+ right = geniCodeRValue (right, TRUE);
+ }
+ else
+ {
+ right = geniCodeRValue (right, FALSE);
+ }
+ return
+ geniCodeAssign (left,
+ geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ right,
+ getResultTypeFromType (tree->ftype)),
+ 0, 1);
}
case LEFT_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
- ,FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeAssign (left,
+ geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
+ ,FALSE),
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0, 1);
case RIGHT_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
- ,FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeAssign (left,
+ geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
+ ,FALSE),
+ geniCodeRValue (right, FALSE)), 0, 1);
case AND_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
- FALSE),
- geniCodeRValue (right, FALSE),
- BITWISEAND,
- operandType (left)), 0);
+ geniCodeAssign (left,
+ geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ geniCodeRValue (right, FALSE),
+ BITWISEAND,
+ operandType (left)), 0, 1);
case XOR_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
- FALSE),
- geniCodeRValue (right, FALSE),
- '^',
- operandType (left)), 0);
+ geniCodeAssign (left,
+ geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+ FALSE),
+ geniCodeRValue (right, FALSE),
+ '^',
+ operandType (left)), 0, 1);
case OR_ASSIGN:
return
- geniCodeAssign (left,
- geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
- ,FALSE),
- geniCodeRValue (right, FALSE),
- '|',
- operandType (left)), 0);
+ geniCodeAssign (left,
+ geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
+ ,FALSE),
+ geniCodeRValue (right, FALSE),
+ '|',
+ operandType (left)), 0, 1);
case ',':
return geniCodeRValue (right, FALSE);
case CALL:
return geniCodeCall (ast2iCode (tree->left,lvl+1),
- tree->right,lvl);
+ tree->right,lvl);
case LABEL:
geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
return ast2iCode (tree->right,lvl+1);
case INLINEASM:
geniCodeInline (tree);
return NULL;
-
+
case ARRAYINIT:
- geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
- return NULL;
+ geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+ return NULL;
+
+ case CRITICAL:
+ geniCodeCritical (tree, lvl);
}
return NULL;
{
loop->next = prev;
if (prev)
- prev->prev = loop;
+ prev->prev = loop;
prev = loop;
}
case VALUE: return "value";
case TYPE: return "type";
}
- return "undefined type";
+ return "undefined type";
}
-operand *validateOpType(operand *op,
- const char *macro,
- const char *args,
- OPTYPE type,
- const char *file,
- unsigned line)
-{
+operand *validateOpType(operand *op,
+ const char *macro,
+ const char *args,
+ OPTYPE type,
+ const char *file,
+ unsigned line)
+{
if (op && op->type == type)
{
- return op;
+ return op;
}
- fprintf(stderr,
- "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
- " expected %s, got %s\n",
- macro, args, file, line,
- opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+ fprintf(stderr,
+ "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+ " expected %s, got %s\n",
+ macro, args, file, line,
+ opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
exit(-1);
return op; // never reached, makes compiler happy.
}