X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.c;h=fe437728ce97f42e0c4663a2e65b8a25a3f8b5df;hb=HEAD;hp=36a4837e9c89a5b7b2c4b0eb77fea7bfaebada77;hpb=18e57deddc09c124d5b86a1b79408c19c8aed7df;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 36a4837e..fe437728 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -25,6 +25,7 @@ #include "common.h" #include "newalloc.h" #include "math.h" +#include "dbuf_string.h" /*-----------------------------------------------------------------*/ /* global variables */ @@ -34,25 +35,27 @@ int iTempNum = 0; int iTempLblNum = 0; int operandKey = 0; int iCodeKey = 0; -char *filename; -int lineno; +char *filename; /* current file name */ +int lineno = 1; /* current line number */ 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) +#define PRINTFUNC(x) void x (struct dbuf_s *dbuf, iCode *ic, char *s) /* forward definition of ic print functions */ PRINTFUNC (picGetValueAtAddr); PRINTFUNC (picSetValueAtAddr); @@ -68,6 +71,8 @@ PRINTFUNC (picJumpTable); PRINTFUNC (picInline); PRINTFUNC (picReceive); PRINTFUNC (picDummyRead); +PRINTFUNC (picCritical); +PRINTFUNC (picEndCritical); iCodeTable codeTable[] = { @@ -76,6 +81,9 @@ 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}, @@ -114,187 +122,162 @@ iCodeTable codeTable[] = {RECEIVE, "recv", picReceive, NULL}, {SEND, "send", picGenericOne, NULL}, {ARRAYINIT, "arrayInit", picGenericOne, NULL}, - {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, 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 */ +/* operandName - returns the name of the operand */ /*-----------------------------------------------------------------*/ +int +printOperand (operand * op, FILE * file) +{ + struct dbuf_s dbuf; + int ret; + int pnl = 0; - -/* 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: -1==-1, not allowed for unsigned types (e.g. in compare) - pedantic>1: "char c=200" is not allowed (evaluates to -56) -*/ - -void checkConstantRange(sym_link *ltype, value *val, char *msg, - int pedantic) { - double max; - int warnings=0; - int negative=0; - long v; - - max = pow ((double)2.0, (double)bitsForType(ltype)); - - if (SPEC_LONG(val->type)) { - if (SPEC_USIGN(val->type)) { - v=SPEC_CVAL(val->type).v_ulong; - } else { - v=SPEC_CVAL(val->type).v_long; - } - } else { - if (SPEC_USIGN(val->type)) { - v=SPEC_CVAL(val->type).v_uint; - } else { - v=SPEC_CVAL(val->type).v_int; - } - } - - -#if 0 - // this could be a good idea - if (options.pedantic) - pedantic=2; -#endif - - if (SPEC_NOUN(ltype)==FLOAT) { - // anything will do - return; - } - - if (!SPEC_USIGN(val->type) && v<0) { - negative=1; - if (SPEC_USIGN(ltype) && (pedantic>1)) { - warnings++; + if (!file) + { + file = stdout; + pnl = 1; } - v=-v; - } - - // if very pedantic: "char c=200" is not allowed - if (pedantic>1 && !SPEC_USIGN(ltype)) { - max = max/2 + negative; - } - - if (v >= max) { - warnings++; - } + dbuf_init (&dbuf, 1024); + ret = dbuf_printOperand(op, &dbuf); + dbuf_write_and_destroy (&dbuf, file); -#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); - werror (W_CONST_RANGE, message); + if (pnl) + putc ('\n', file); - if (pedantic>1) - fatalError++; - } -#endif + return ret; } -/*-----------------------------------------------------------------*/ -/* operandName - returns the name of the operand */ -/*-----------------------------------------------------------------*/ -int -printOperand (operand * op, FILE * file) +int +dbuf_printOperand (operand * op, struct dbuf_s *dbuf) { sym_link *opetype; - int pnl = 0; if (!op) return 1; - if (!file) - { - file = stdout; - pnl = 1; - } switch (op->type) { case VALUE: opetype = getSpec (operandType (op)); - if (SPEC_NOUN (opetype) == V_FLOAT) - fprintf (file, "%g {", SPEC_CVAL (opetype).v_float); + if (IS_FLOAT (opetype)) + dbuf_printf (dbuf, "%g {", SPEC_CVAL (opetype).v_float); + else if (IS_FIXED16X16 (opetype)) + dbuf_printf (dbuf, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16)); else - fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand)); - printTypeChain (operandType (op), file); - fprintf (file, "}"); + dbuf_printf (dbuf, "0x%x {", (unsigned int) ulFromVal (op->operand.valOperand)); + dbuf_printTypeChain (operandType (op), dbuf); + dbuf_append_char (dbuf, '}'); 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")) { + dbuf_printf (dbuf, "%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, "}"); + dbuf_append_char (dbuf, '{'); + dbuf_printTypeChain (operandType (op), dbuf); + if (SPIL_LOC (op) && IS_ITEMP (op)) + dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname); + dbuf_append_char (dbuf, '}'); } /* 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) + dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ? + OP_SYMBOL (op)->usl.spillLoc->rname : + OP_SYMBOL (op)->usl.spillLoc->name)); + else + dbuf_append_str (dbuf, "[err]"); + else + dbuf_append_str (dbuf, "[remat]"); + } + else + { + int i; + dbuf_append_char (dbuf, '['); + for (i = 0; i < OP_SYMBOL (op)->nRegs; i++) + dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i])); + dbuf_append_char (dbuf, ']'); + } + } +//#else /* } else { */ + } else { + /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */ + dbuf_printf (dbuf, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name)); + + if(getenv("PRINT_SHORT_OPERANDS")[0] < '1') + { + dbuf_printf (dbuf, "[lr%d:%d so:%d]", + OP_LIVEFROM (op), OP_LIVETO (op), + OP_SYMBOL (op)->stack); + } + + if(getenv("PRINT_SHORT_OPERANDS")[0] < '2') + { + dbuf_append_char (dbuf, '{'); + dbuf_printTypeChain (operandType (op), dbuf); + if (SPIL_LOC (op) && IS_ITEMP (op)) + dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname); + dbuf_append_char (dbuf, '}'); + } + /* 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) + dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ? + OP_SYMBOL (op)->usl.spillLoc->rname : + OP_SYMBOL (op)->usl.spillLoc->name)); + else + dbuf_append_str (dbuf, "[err]"); + else + dbuf_append_str (dbuf, "[remat]"); + } + else + { + int i; + dbuf_append_char (dbuf, '['); + for (i = 0; i < OP_SYMBOL (op)->nRegs; i++) + dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i])); + dbuf_append_char (dbuf, ']'); + } + } +//#endif /* } */ + } break; case TYPE: - fprintf (file, "("); - printTypeChain (op->operand.typeOperand, file); - fprintf (file, ")"); + dbuf_append_char (dbuf, '('); + dbuf_printTypeChain (op->operand.typeOperand, dbuf); + dbuf_append_char (dbuf, ')'); break; } - if (pnl) - fprintf (file, "\n"); return 0; } @@ -304,172 +287,196 @@ printOperand (operand * op, FILE * file) /*-----------------------------------------------------------------*/ PRINTFUNC (picGetValueAtAddr) { - fprintf (of, "\t"); - printOperand (IC_RESULT (ic), of); - fprintf (of, " = "); - fprintf (of, "@["); - printOperand (IC_LEFT (ic), of); - fprintf (of, "]"); - - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_printOperand (IC_RESULT (ic), dbuf); + dbuf_append_str (dbuf, " = "); + dbuf_append_str (dbuf, "@["); + dbuf_printOperand (IC_LEFT (ic), dbuf); + dbuf_append_str (dbuf, "]\n"); } PRINTFUNC (picSetValueAtAddr) { - fprintf (of, "\t"); - fprintf (of, "*["); - printOperand (IC_LEFT (ic), of); - fprintf (of, "] = "); - printOperand (IC_RIGHT (ic), of); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_append_str (dbuf, "*["); + dbuf_printOperand (IC_LEFT (ic), dbuf); + dbuf_append_str (dbuf, "] = "); + dbuf_printOperand (IC_RIGHT (ic), dbuf); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picAddrOf) { - fprintf (of, "\t"); - printOperand (IC_RESULT (ic), of); + dbuf_append_char (dbuf, '\t'); + dbuf_printOperand (IC_RESULT (ic), dbuf); if (IS_ITEMP (IC_LEFT (ic))) - fprintf (of, " = "); + dbuf_append_str (dbuf, " = "); else - fprintf (of, " = &["); - printOperand (IC_LEFT (ic), of); + dbuf_append_str (dbuf, " = &["); + dbuf_printOperand (IC_LEFT (ic), dbuf); if (IC_RIGHT (ic)) { if (IS_ITEMP (IC_LEFT (ic))) - fprintf (of, " offsetAdd "); + dbuf_append_str (dbuf, " offsetAdd "); else - fprintf (of, " , "); - printOperand (IC_RIGHT (ic), of); + dbuf_append_str (dbuf, " , "); + dbuf_printOperand (IC_RIGHT (ic), dbuf); } if (IS_ITEMP (IC_LEFT (ic))) - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\n'); else - fprintf (of, "]\n"); + dbuf_append_str (dbuf, "]\n"); } PRINTFUNC (picJumpTable) { symbol *sym; - fprintf (of, "\t"); - fprintf (of, "%s\t", s); - printOperand (IC_JTCOND (ic), of); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_printf (dbuf, "%s\t", s); + dbuf_printOperand (IC_JTCOND (ic), dbuf); for (sym = setFirstItem (IC_JTLABELS (ic)); sym; sym = setNextItem (IC_JTLABELS (ic))) - fprintf (of, "\t\t\t%s\n", sym->name); + dbuf_printf (dbuf, "; %s", sym->name); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picGeneric) { - fprintf (of, "\t"); - printOperand (IC_RESULT (ic), of); - fprintf (of, " = "); - printOperand (IC_LEFT (ic), of); - fprintf (of, " %s ", s); - printOperand (IC_RIGHT (ic), of); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_printOperand (IC_RESULT (ic), dbuf); + dbuf_append_str (dbuf, " = "); + dbuf_printOperand (IC_LEFT (ic), dbuf); + dbuf_printf (dbuf, " %s ", s); + dbuf_printOperand (IC_RIGHT (ic), dbuf); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picGenericOne) { - fprintf (of, "\t"); + dbuf_append_char (dbuf, '\t'); if (IC_RESULT (ic)) { - printOperand (IC_RESULT (ic), of); - fprintf (of, " = "); + dbuf_printOperand (IC_RESULT (ic), dbuf); + dbuf_append_str (dbuf, " = "); } if (IC_LEFT (ic)) { - fprintf (of, "%s ", s); - printOperand (IC_LEFT (ic), of); + dbuf_printf (dbuf, "%s ", s); + dbuf_printOperand (IC_LEFT (ic), dbuf); } if (!IC_RESULT (ic) && !IC_LEFT (ic)) - fprintf (of, s); + dbuf_append_str (dbuf, s); if (ic->op == SEND || ic->op == RECEIVE) { - fprintf(of,"{argreg = %d}",ic->argreg); + dbuf_printf (dbuf,"{argreg = %d}",ic->argreg); + } + if (ic->op == IPUSH) { + dbuf_printf (dbuf,"{parmPush = %d}",ic->parmPush); } - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picCast) { - fprintf (of, "\t"); - printOperand (IC_RESULT (ic), of); - fprintf (of, " = "); - printOperand (IC_LEFT (ic), of); - printOperand (IC_RIGHT (ic), of); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_printOperand (IC_RESULT (ic), dbuf); + dbuf_append_str (dbuf, " = "); + dbuf_printOperand (IC_LEFT (ic), dbuf); + dbuf_printOperand (IC_RIGHT (ic), dbuf); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picAssign) { - fprintf (of, "\t"); + dbuf_append_char (dbuf, '\t'); if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic))) - fprintf (of, "*("); + dbuf_append_str (dbuf, "*("); - printOperand (IC_RESULT (ic), of); + dbuf_printOperand (IC_RESULT (ic), dbuf); if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic))) - fprintf (of, ")"); + dbuf_append_char (dbuf, ')'); - fprintf (of, " %s ", s); - printOperand (IC_RIGHT (ic), of); + dbuf_printf (dbuf, " %s ", s); + dbuf_printOperand (IC_RIGHT (ic), dbuf); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picLabel) { - fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key); + dbuf_printf (dbuf, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key); } PRINTFUNC (picGoto) { - fprintf (of, "\t"); - fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key); + dbuf_append_char (dbuf, '\t'); + dbuf_printf (dbuf, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key); } PRINTFUNC (picIfx) { - fprintf (of, "\t"); - fprintf (of, "if "); - printOperand (IC_COND (ic), of); + dbuf_append_char (dbuf, '\t'); + dbuf_append_str (dbuf, "if "); + dbuf_printOperand (IC_COND (ic), dbuf); if (!IC_TRUE (ic)) - fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key); + dbuf_printf (dbuf, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key); else { - fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key); + dbuf_printf (dbuf, " != 0 goto %s($%d)", IC_TRUE (ic)->name, IC_TRUE (ic)->key); if (IC_FALSE (ic)) - fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name); + dbuf_printf (dbuf, "; zzgoto %s\n", IC_FALSE (ic)->name); + dbuf_append_char (dbuf, '\n'); } } PRINTFUNC (picInline) { - fprintf (of, "%s", IC_INLINE (ic)); + dbuf_append_str (dbuf, IC_INLINE (ic)); } PRINTFUNC (picReceive) { - printOperand (IC_RESULT (ic), of); - fprintf (of, " = %s ", s); - printOperand (IC_LEFT (ic), of); - fprintf (of, "\n"); + dbuf_printOperand (IC_RESULT (ic), dbuf); + dbuf_printf (dbuf, " = %s ", s); + dbuf_printOperand (IC_LEFT (ic), dbuf); + dbuf_append_char (dbuf, '\n'); } PRINTFUNC (picDummyRead) { - fprintf (of, "\t"); - fprintf (of, "%s ", s); - printOperand (IC_RIGHT (ic), of); - fprintf (of, "\n"); + dbuf_append_char (dbuf, '\t'); + dbuf_printf (dbuf, "%s ", s); + dbuf_printOperand (IC_RIGHT (ic), dbuf); + dbuf_append_char (dbuf, '\n'); +} + +PRINTFUNC (picCritical) +{ + dbuf_append_char (dbuf, '\t'); + if (IC_RESULT (ic)) + dbuf_printOperand (IC_RESULT (ic), dbuf); + else + dbuf_append_str (dbuf, "(stack)"); + dbuf_printf (dbuf, " = %s ", s); + dbuf_append_char (dbuf, '\n'); +} + +PRINTFUNC (picEndCritical) +{ + dbuf_append_char (dbuf, '\t'); + dbuf_printf (dbuf, "%s = ", s); + if (IC_RIGHT (ic)) + dbuf_printOperand (IC_RIGHT (ic), dbuf); + else + dbuf_append_str (dbuf, "(stack)"); + dbuf_append_char (dbuf, '\n'); } /*-----------------------------------------------------------------*/ @@ -480,21 +487,24 @@ piCode (void *item, FILE * of) { iCode *ic = item; iCodeTable *icTab; + struct dbuf_s dbuf; if (!of) 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); - icTab->iCodePrint (of, ic, icTab->printName); + fprintf (of, "%s(%d:%d:%d:%d:%d)\t", + ic->filename, ic->lineno, + ic->seq, ic->key, ic->depth, ic->supportRtn); + dbuf_init (&dbuf, 1024); + icTab->iCodePrint (&dbuf, ic, icTab->printName); + dbuf_write_and_destroy (&dbuf, of); return 1; } void PICC(iCode *ic) { - printiCChain(ic,stdout); + printiCChain(ic,stdout); } /*-----------------------------------------------------------------*/ /* printiCChain - prints intermediate code for humans */ @@ -504,19 +514,24 @@ printiCChain (iCode * icChain, FILE * of) { iCode *loop; iCodeTable *icTab; + struct dbuf_s dbuf; if (!of) of = stdout; 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); - - icTab->iCodePrint (of, loop, icTab->printName); - } + { + 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); + + dbuf_init(&dbuf, 1024); + icTab->iCodePrint (&dbuf, loop, icTab->printName); + dbuf_write_and_destroy (&dbuf, of); + //// + fflush(of); + } } } @@ -545,8 +560,9 @@ newiCode (int op, operand * left, operand * right) ic = Safe_alloc ( sizeof (iCode)); - ic->lineno = lineno; + ic->seqPoint = seqPoint; ic->filename = filename; + ic->lineno = lineno; ic->block = block; ic->level = scopeLevel; ic->op = op; @@ -562,8 +578,8 @@ newiCode (int op, operand * left, operand * right) /*-----------------------------------------------------------------*/ iCode * newiCodeCondition (operand * condition, - symbol * trueLabel, - symbol * falseLabel) + symbol * trueLabel, + symbol * falseLabel) { iCode *ic; @@ -611,7 +627,7 @@ newiTemp (char *s) { SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++); } - + itmp = newSymbol (buffer, 1); strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX); itmp->isitmp = 1; @@ -627,13 +643,13 @@ newiTempLabel (char *s) { 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 { @@ -649,14 +665,15 @@ newiTempLabel (char *s) } /*-----------------------------------------------------------------*/ -/* newiTempPreheaderLabel - creates a new preheader label */ +/* newiTempLoopHeaderLabel - creates a new loop header label */ /*-----------------------------------------------------------------*/ symbol * -newiTempPreheaderLabel () +newiTempLoopHeaderLabel (bool pre) { symbol *itmplbl; - SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++); + SNPRINTF (buffer, sizeof(buffer), pre ? "preHeaderLbl%d" : LOOPEXITLBL "%d", + iTempLblNum++); itmplbl = newSymbol (buffer, 1); itmplbl->isitmp = 1; @@ -670,7 +687,7 @@ newiTempPreheaderLabel () /*-----------------------------------------------------------------*/ /* initiCode - initialises some iCode related stuff */ /*-----------------------------------------------------------------*/ -void +void initiCode () { @@ -684,8 +701,8 @@ copyiCode (iCode * ic) { iCode *nic = newiCode (ic->op, NULL, NULL); - nic->lineno = ic->lineno; nic->filename = ic->filename; + nic->lineno = ic->lineno; nic->block = ic->block; nic->level = ic->level; nic->parmBytes = ic->parmBytes; @@ -763,7 +780,7 @@ newiTempOperand (sym_link * type, char throwType) /* 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; @@ -784,7 +801,6 @@ operandType (operand * op) /* depending on type of operand */ switch (op->type) { - case VALUE: return op->operand.valOperand->type; @@ -793,30 +809,49 @@ operandType (operand * op) case TYPE: 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; } } +/*-----------------------------------------------------------------*/ +/* operandSize - returns size of an operand in bytes */ +/*-----------------------------------------------------------------*/ +unsigned int +operandSize (operand * op) +{ + sym_link *type; + + /* if nothing return 0 */ + if (!op) + return 0; + + type = operandType (op); + if (op->aggr2ptr == 2) + type = type->next; + return getSize (type); +} + /*-----------------------------------------------------------------*/ /* 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; @@ -825,7 +860,7 @@ isParameterToCall (value * args, operand * op) /*-----------------------------------------------------------------*/ /* isOperandGlobal - return 1 if operand is a global variable */ /*-----------------------------------------------------------------*/ -int +int isOperandGlobal (operand * op) { if (!op) @@ -847,7 +882,7 @@ isOperandGlobal (operand * op) /*-----------------------------------------------------------------*/ /* isOperandVolatile - return 1 if the operand is volatile */ /*-----------------------------------------------------------------*/ -int +int isOperandVolatile (operand * op, bool chkTemp) { sym_link *optype; @@ -857,19 +892,19 @@ isOperandVolatile (operand * op, bool chkTemp) return 0; opetype = getSpec (optype = operandType (op)); - - if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype)) - return 1; - - if (IS_VOLATILE (opetype)) - return 1; - return 0; + + 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; @@ -888,7 +923,7 @@ isOperandLiteral (operand * op) /*-----------------------------------------------------------------*/ /* isOperandInFarSpace - will return true if operand is in farSpace */ /*-----------------------------------------------------------------*/ -bool +bool isOperandInFarSpace (operand * op) { sym_link *etype; @@ -902,9 +937,9 @@ isOperandInFarSpace (operand * op) 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 { @@ -913,10 +948,38 @@ isOperandInFarSpace (operand * op) return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE); } +/*-----------------------------------------------------------------*/ +/* isOperandInPagedSpace - return true if operand is in pagedSpace */ +/*-----------------------------------------------------------------*/ +bool +isOperandInPagedSpace (operand * op) +{ + sym_link *etype; + + if (!op) + return FALSE; + + if (!IS_SYMOP (op)) + return FALSE; + + if (!IS_TRUE_SYMOP (op)) + { + if (SPIL_LOC (op)) + etype = SPIL_LOC (op)->etype; + else + return FALSE; + } + else + { + etype = getSpec (operandType (op)); + } + return (IN_PAGEDSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE); +} + /*------------------------------------------------------------------*/ /* isOperandInDirSpace - will return true if operand is in dirSpace */ /*------------------------------------------------------------------*/ -bool +bool isOperandInDirSpace (operand * op) { sym_link *etype; @@ -930,9 +993,9 @@ isOperandInDirSpace (operand * op) 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 { @@ -944,7 +1007,7 @@ isOperandInDirSpace (operand * op) /*--------------------------------------------------------------------*/ /* isOperandInCodeSpace - will return true if operand is in codeSpace */ /*--------------------------------------------------------------------*/ -bool +bool isOperandInCodeSpace (operand * op) { sym_link *etype; @@ -960,9 +1023,9 @@ isOperandInCodeSpace (operand * op) 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 { @@ -974,7 +1037,7 @@ isOperandInCodeSpace (operand * op) /*-----------------------------------------------------------------*/ /* isOperandOnStack - will return true if operand is on stack */ /*-----------------------------------------------------------------*/ -bool +bool isOperandOnStack (operand * op) { sym_link *etype; @@ -994,6 +1057,55 @@ isOperandOnStack (operand * op) 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 */ /*-----------------------------------------------------------------*/ @@ -1015,13 +1127,13 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms) *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))); @@ -1035,7 +1147,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms) /*-----------------------------------------------------------------*/ 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; @@ -1051,19 +1163,19 @@ operandOperation (operand * left, operand * right, { 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 @@ -1078,167 +1190,210 @@ operandOperation (operand * left, operand * right, if (IS_INT (type) || !IS_SPEC (type)) { - /* long is handled here, because it can overflow with double */ - if (SPEC_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 (SPEC_USIGN (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 (!options.lessPedantic && - 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 (!options.lessPedantic && - l != (TYPE_WORD) l) - werror (W_INT_OVL); - } - } + /* 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_TARGET_ULONG) double2ul (operandLitValue (left)) * + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)))); + else if (IS_UNSIGNED (type)) /* unsigned int */ + { + /* unsigned int is handled here in order to detect overflow */ + TYPE_TARGET_ULONG ul = (TYPE_TARGET_UINT) double2ul (operandLitValue (left)) * + (TYPE_TARGET_UINT) double2ul (operandLitValue (right)); + + retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_UINT) ul)); + if (ul != (TYPE_TARGET_UINT) ul) + werror (W_INT_OVL); + } + else /* signed int */ + { + /* signed int is handled here in order to detect overflow */ + TYPE_TARGET_LONG l = (TYPE_TARGET_INT) operandLitValue (left) * + (TYPE_TARGET_INT) operandLitValue (right); + + retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_INT) l)); + if (l != (TYPE_TARGET_INT) l) + werror (W_INT_OVL); + } + } else - /* all others go here: */ - retval = operandFromValue (valCastLiteral (type, - operandLitValue (left) * - operandLitValue (right))); + /* all others go here: */ + retval = operandFromValue (valCastLiteral (type, + operandLitValue (left) * + operandLitValue (right))); break; case '/': - if ((TYPE_UDWORD) operandLitValue (right) == 0) - { - werror (E_DIVIDE_BY_ZERO); - retval = right; - - } + if (IS_UNSIGNED (type)) + { + if ((TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0) + { + werror (E_DIVIDE_BY_ZERO); + retval = right; + } + SPEC_USIGN (let) = 1; + SPEC_USIGN (ret) = 1; + retval = operandFromValue (valCastLiteral (type, + (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) / + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)))); + } else - retval = operandFromValue (valCastLiteral (type, - operandLitValue (left) / - operandLitValue (right))); + { + if (operandLitValue (right) == 0) + { + werror (E_DIVIDE_BY_ZERO); + retval = right; + } + retval = operandFromValue (valCastLiteral (type, + operandLitValue (left) / + operandLitValue (right))); + } break; case '%': - if ((TYPE_UDWORD) operandLitValue (right) == 0) { - werror (E_DIVIDE_BY_ZERO); - retval = right; - } + if ((TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0) + { + werror (E_DIVIDE_BY_ZERO); + retval = right; + } else { - if (SPEC_USIGN(let) || SPEC_USIGN(ret)) - /* one of the operands is unsigned */ - retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) % - (TYPE_UDWORD) operandLitValue (right)); - else - /* both operands are signed */ - retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) % - (TYPE_DWORD) operandLitValue (right)); + if (IS_UNSIGNED (type)) + retval = operandFromLit ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) % + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))); + else + retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) % + (TYPE_TARGET_LONG) operandLitValue (right)); } break; case LEFT_OP: /* The number of left shifts is always unsigned. Signed doesn't make - sense here. Shifting by a negative number is impossible. */ - retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) << - (TYPE_UDWORD) operandLitValue (right)); + sense here. Shifting by a negative number is impossible. */ + retval = operandFromValue (valCastLiteral (type, + ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) << + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))))); break; 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 (SPEC_USIGN(let)) + 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)); + retval = operandFromLit ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) >> + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))); else /* signed: arithmetic shift right */ - retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >> - (TYPE_UDWORD) operandLitValue (right)); + retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) >> + (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))); break; case EQ_OP: - /* this op doesn't care about signedness */ - { - TYPE_UDWORD l, r; - - l = (TYPE_UDWORD) operandLitValue (left); - if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR) - l &= 0xff; - else if (!SPEC_LONG (OP_VALUE(left)->type)) - l &= 0xffff; - r = (TYPE_UDWORD) operandLitValue (right); - if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR) - r &= 0xff; - else if (!SPEC_LONG (OP_VALUE(right)->type)) - r &= 0xffff; - retval = operandFromLit (l == r); - } + 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_TARGET_ULONG l, r; + + l = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)); + r = (TYPE_TARGET_ULONG) double2ul (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_TARGET_UINT) r; + l = (TYPE_TARGET_UINT) 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 = operandFromValue (valCastLiteral (type, - (TYPE_UDWORD)operandLitValue(left) & - (TYPE_UDWORD)operandLitValue(right))); + (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) & + (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)))); break; case '|': retval = operandFromValue (valCastLiteral (type, - (TYPE_UDWORD)operandLitValue(left) | - (TYPE_UDWORD)operandLitValue(right))); + (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) | + (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)))); break; case '^': retval = operandFromValue (valCastLiteral (type, - (TYPE_UDWORD)operandLitValue(left) ^ - (TYPE_UDWORD)operandLitValue(right))); + (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) ^ + (TYPE_TARGET_ULONG) double2ul (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: { - TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left); + TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) double2ul (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: { - TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left); + TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) double2ul (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_TARGET_ULONG) double2ul (operandLitValue(left)) >> + (TYPE_TARGET_ULONG) double2ul (operandLitValue(right))) & 1); + break; + case GETBYTE: + retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >> + (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)) & 0xFF)); + break; + case GETWORD: + retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >> + (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)) & 0xFFFF)); + break; + + case GETHBIT: + retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >> + ((getSize (let) * 8) - 1)) & 1); + break; case UNARYMINUS: retval = operandFromValue (valCastLiteral (type, @@ -1246,7 +1401,8 @@ operandOperation (operand * left, operand * right, break; case '~': - retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left))); + retval = operandFromValue (valCastLiteral (type, + ~((TYPE_TARGET_ULONG) double2ul (operandLitValue (left))))); break; case '!': @@ -1255,7 +1411,7 @@ operandOperation (operand * left, operand * right, default: werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - " operandOperation invalid operator "); + " operandOperation invalid operator "); assert (0); } @@ -1288,14 +1444,16 @@ isOperandEqual (operand * left, operand * right) { 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; @@ -1304,7 +1462,7 @@ isOperandEqual (operand * left, operand * right) /*-------------------------------------------------------------------*/ /* isiCodeEqual - compares two iCodes are equal, returns true if yes */ /*-------------------------------------------------------------------*/ -int +int isiCodeEqual (iCode * left, iCode * right) { /* if the same pointer */ @@ -1321,23 +1479,23 @@ isiCodeEqual (iCode * left, iCode * right) /* 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; @@ -1454,21 +1612,20 @@ operandFromSymbol (symbol * sym) 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 */ ) { @@ -1476,6 +1633,7 @@ operandFromSymbol (symbol * sym) 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; @@ -1598,7 +1756,7 @@ operandFromAst (ast * tree,int lvl) default: assert (0); } - + /* Just to keep the compiler happy */ return (operand *) 0; } @@ -1606,7 +1764,7 @@ operandFromAst (ast * tree,int lvl) /*-----------------------------------------------------------------*/ /* setOperandType - sets the operand's type to the given type */ /*-----------------------------------------------------------------*/ -void +void setOperandType (operand * op, sym_link * type) { /* depending on the type of operand */ @@ -1615,18 +1773,18 @@ setOperandType (operand * op, sym_link * type) 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: @@ -1635,10 +1793,11 @@ setOperandType (operand * op, sym_link * type) } } + /*-----------------------------------------------------------------*/ /* Get size in byte of ptr need to access an array */ /*-----------------------------------------------------------------*/ -int +static unsigned int getArraySizePtr (operand * op) { sym_link *ltype = operandType(op); @@ -1646,29 +1805,32 @@ getArraySizePtr (operand * 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); } @@ -1676,35 +1838,54 @@ getArraySizePtr (operand * op) /*-----------------------------------------------------------------*/ /* 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; } @@ -1733,7 +1914,7 @@ geniCodeRValue (operand * op, bool force) /* 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; @@ -1742,7 +1923,7 @@ geniCodeRValue (operand * op, bool force) 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); @@ -1766,10 +1947,41 @@ geniCodeRValue (operand * op, bool force) return IC_RESULT (ic); } +static DECLARATOR_TYPE +getPtrType(sym_link *type) +{ + //for Z80 anything goes + if (TARGET_Z80_LIKE) + return POINTER; + + //preserve original behaviour for PIC16 + if (TARGET_IS_PIC16) + return POINTER; + + //for HC08 only zeropage ptr is different + if (TARGET_IS_HC08) + { + if (IS_DATA_PTR (type)) + return POINTER; + else + return FPOINTER; + } + + if (IS_DATA_PTR (type) && TARGET_MCS51_LIKE) + return IPOINTER; + if (IS_PTR (type)) + return DCL_TYPE (type); + else if (IS_FUNC (type)) + return CPOINTER; + else if (IS_ARRAY (type)) + return PTR_TYPE (SPEC_OCLS (getSpec (type))); + return UPOINTER; +} + /*-----------------------------------------------------------------*/ /* geniCodeCast - changes the value from one type to another */ /*-----------------------------------------------------------------*/ -operand * +static operand * geniCodeCast (sym_link * type, operand * op, bool implicit) { iCode *ic; @@ -1785,66 +1997,84 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) 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++; + } } } } @@ -1853,24 +2083,33 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) } /* 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 assignment 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)))) + (IS_DECL (type) && IS_DECL (optype) && getPtrType (type) == getPtrType (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); } @@ -1878,10 +2117,12 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /* 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); } @@ -1889,7 +2130,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /*-----------------------------------------------------------------*/ /* geniCodeLabel - will create a Label */ /*-----------------------------------------------------------------*/ -void +void geniCodeLabel (symbol * label) { iCode *ic; @@ -1901,7 +2142,7 @@ geniCodeLabel (symbol * label) /*-----------------------------------------------------------------*/ /* geniCodeGoto - will create a Goto */ /*-----------------------------------------------------------------*/ -void +void geniCodeGoto (symbol * label) { iCode *ic; @@ -1913,8 +2154,8 @@ geniCodeGoto (symbol * label) /*-----------------------------------------------------------------*/ /* 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; @@ -1924,48 +2165,54 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) /* 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_TARGET_ULONG) ulFromVal (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 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 > 0) && !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 */ /* if the size left or right > 1 then support routine */ if (getSize (ltype) > 1 || getSize (rtype) > 1) - ic->supportRtn = 1; - + { + if (IS_LITERAL (retype)) + ic = newiCode ('*', right, left); /* multiplication by support routine with one literal */ + else + ic = newiCode ('*', left, right); /* multiplication by support routine */ + ic->supportRtn = 1; + } + else + { + ic = newiCode ('*', left, right); /* normal multiplication */ + } } IC_RESULT (ic) = newiTempOperand (resType, 1); @@ -1976,8 +2223,8 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) /*-----------------------------------------------------------------*/ /* 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; @@ -1987,24 +2234,24 @@ geniCodeDivision (operand * left, operand * right) 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 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_TARGET_ULONG) ulFromVal (right->operand.valOperand))) > 0)) { 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); @@ -2014,8 +2261,8 @@ geniCodeDivision (operand * left, operand * right) /*-----------------------------------------------------------------*/ /* 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; @@ -2024,9 +2271,9 @@ geniCodeModulus (operand * left, operand * right) /* 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); @@ -2054,7 +2301,7 @@ geniCodePtrPtrSubtract (operand * left, operand * right) if (IS_LITERAL (letype) && IS_LITERAL (retype)) { result = operandFromValue (valMinus (left->operand.valOperand, - right->operand.valOperand)); + right->operand.valOperand)); goto subtractExit; } @@ -2070,14 +2317,15 @@ 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; @@ -2093,19 +2341,22 @@ geniCodeSubtract (operand * left, operand * right) 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); @@ -2114,7 +2365,8 @@ geniCodeSubtract (operand * left, operand * 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); @@ -2124,22 +2376,23 @@ geniCodeSubtract (operand * left, operand * right) /*-----------------------------------------------------------------*/ /* 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 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 */ @@ -2147,22 +2400,30 @@ geniCodeAdd (operand * left, operand * right, int lvl) { 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, resultType); + /* 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); @@ -2171,7 +2432,8 @@ geniCodeAdd (operand * left, operand * right, int lvl) /* 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); @@ -2181,7 +2443,7 @@ geniCodeAdd (operand * left, operand * right, int lvl) } /*-----------------------------------------------------------------*/ -/* 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) @@ -2189,7 +2451,6 @@ aggrToPtr (sym_link * type, bool force) sym_link *etype; sym_link *ptype; - if (IS_PTR (type) && !force) return type; @@ -2198,43 +2459,35 @@ aggrToPtr (sym_link * type, bool force) ptype->next = type; - /* 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; + /* set the pointer depending on the storage class */ + DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype)); + return ptype; +} - /* the variable was volatile then pointer to volatile */ - if (IS_VOLATILE (etype)) - DCL_PTR_VOLATILE (ptype) = 1; +/*------------------------------------------------------------------*/ +/* 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 ptype; + /* 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); /* 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; + DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype)); op->isaddr = 0; return op; @@ -2244,48 +2497,72 @@ geniCodeArray2Ptr (operand * 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; + RESULT_TYPE resultType; - if (IS_PTR (ltype)) + resultType = (getArraySizePtr(left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR; + if (DCL_ELEM (ltype)) { - if (IS_PTR (ltype->next) && left->isaddr) - { - left = geniCodeRValue (left, FALSE); - } - return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl); + if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255) + resultType = RESULT_TYPE_CHAR; } - right = geniCodeMultiply (right, - operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE)); + if (IS_PTR (ltype)) + { + if (IS_PTR (ltype->next) && left->isaddr) + { + left = geniCodeRValue (left, FALSE); + } + return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl), + lvl); + } + size = operandFromLit (getSize (ltype->next)); + SPEC_USIGN (getSpec (operandType (size))) = 1; + indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); + right = geniCodeMultiply (right, size, resultType); + /* 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) @@ -2295,10 +2572,10 @@ 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)); @@ -2310,13 +2587,13 @@ geniCodeStruct (operand * left, operand * right, bool islval) 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)); } @@ -2332,8 +2609,8 @@ geniCodePostInc (operand * op) 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; @@ -2350,18 +2627,22 @@ geniCodePostInc (operand * op) 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; @@ -2371,13 +2652,13 @@ geniCodePostInc (operand * op) /* 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; @@ -2388,17 +2669,23 @@ geniCodePreInc (operand * op) 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; } /*-----------------------------------------------------------------*/ @@ -2412,8 +2699,8 @@ geniCodePostDec (operand * op) 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; @@ -2430,18 +2717,22 @@ geniCodePostDec (operand * op) 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; @@ -2451,13 +2742,13 @@ geniCodePostDec (operand * op) /* 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; @@ -2468,26 +2759,32 @@ geniCodePreDec (operand * op) 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; } /*-----------------------------------------------------------------*/ -/* geniCodeBitwise - gen int code for bitWise operators */ +/* geniCodeBitwise - gen int code for bitWise operators */ /*-----------------------------------------------------------------*/ operand * geniCodeBitwise (operand * left, operand * right, - int oper, sym_link * resType) + int oper, sym_link * resType) { iCode *ic; @@ -2512,6 +2809,13 @@ geniCodeAddressOf (operand * op) 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)) { */ @@ -2522,15 +2826,7 @@ geniCodeAddressOf (operand * op) p = newLink (DECLARATOR); /* 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; + DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype)); p->next = copyLinkChain (optype); @@ -2542,17 +2838,18 @@ geniCodeAddressOf (operand * op) return op; } - /* other wise make this of the type coming in */ + /* otherwise make this of the type coming in */ ic = newiCode (ADDRESS_OF, op, NULL); IC_RESULT (ic) = newiTempOperand (p, 1); IC_RESULT (ic)->isaddr = 0; ADDTOCHAIN (ic); return IC_RESULT (ic); } + /*-----------------------------------------------------------------*/ /* setOClass - sets the output class depending on the pointer type */ /*-----------------------------------------------------------------*/ -void +void setOClass (sym_link * ptr, sym_link * spec) { switch (DCL_TYPE (ptr)) @@ -2623,23 +2920,18 @@ geniCodeDerefPtr (operand * op,int lvl) else { retype = getSpec (rtype = copyLinkChain (optype->next)); + /* outputclass needs 2b updated */ + setOClass (optype, retype); } - /* outputclass needs 2b updated */ - 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); @@ -2671,12 +2963,15 @@ geniCodeUnaryMinus (operand * op) /* 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); } @@ -2698,11 +2993,11 @@ geniCodeRightShift (operand * left, operand * right) /*-----------------------------------------------------------------*/ /* geniCodeLogic- logic code */ /*-----------------------------------------------------------------*/ -operand * -geniCodeLogic (operand * left, operand * right, int op) +static operand * +geniCodeLogic (operand * left, operand * right, int op, ast *tree) { iCode *ic; - sym_link *ctype; + sym_link *ctype, *ttype; sym_link *rtype = operandType (right); sym_link *ltype = operandType (left); @@ -2710,14 +3005,68 @@ geniCodeLogic (operand * left, operand * right, int op) 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); + CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE); + switch (ccr_result) + { + case CCR_ALWAYS_TRUE: + case CCR_ALWAYS_FALSE: + if (!options.lessPedantic) + werror (W_COMP_RANGE, "true resp. false"); + return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0); + default: + break; + } } - ctype = usualBinaryConversions (&left, &right); + /* 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, RESULT_TYPE_BIT, 0); ic = newiCode (op, left, right); - IC_RESULT (ic) = newiTempOperand (newCharLink (), 1); + /* store 0 or 1 in result */ + ttype = (tree && IS_BIT (tree->ftype)) ? newBoolLink() : newCharLink(); + IC_RESULT (ic) = newiTempOperand (ttype, 1); /* if comparing float and not a '==' || '!=' || '&&' || '||' (these @@ -2727,6 +3076,10 @@ geniCodeLogic (operand * left, operand * right, int op) 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); @@ -2734,7 +3087,74 @@ geniCodeLogic (operand * left, operand * right, int op) } /*-----------------------------------------------------------------*/ -/* 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 = (IS_BIT (tree->ftype)) ? 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) @@ -2746,6 +3166,19 @@ 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 */ /*-----------------------------------------------------------------*/ @@ -2755,18 +3188,19 @@ geniCodeConditional (ast * tree,int lvl) iCode *ic; symbol *falseLabel = newiTempLabel (NULL); symbol *exitLabel = newiTempLabel (NULL); - operand *cond = ast2iCode (tree->left,lvl+1); - operand *true, *false, *result; + ast *astTrue = tree->right->left; + ast *astFalse = tree->right->right; + operand *cond = ast2iCode (tree->left, lvl+1); + operand *result = newiTempOperand (tree->ftype, 0); + operand *opTrue, *opFalse; - ic = newiCodeCondition (geniCodeRValue (cond, FALSE), - NULL, falseLabel); + ic = newiCodeCondition (geniCodeRValue (cond, FALSE), NULL, falseLabel); ADDTOCHAIN (ic); - true = ast2iCode (tree->right->left,lvl+1); + opTrue = ast2iCode (astTrue, lvl+1); - /* move the value to a new Operand */ - result = newiTempOperand (tree->right->ftype, 0); - geniCodeAssign (result, geniCodeRValue (true, FALSE), 0); + /* move the value to the new operand */ + geniCodeAssign (result, geniCodeRValue (opTrue, FALSE), 0, 0); /* generate an unconditional goto */ geniCodeGoto (exitLabel); @@ -2774,8 +3208,8 @@ geniCodeConditional (ast * tree,int lvl) /* now for the right side */ geniCodeLabel (falseLabel); - false = ast2iCode (tree->right->right,lvl+1); - geniCodeAssign (result, geniCodeRValue (false, FALSE), 0); + opFalse = ast2iCode (astFalse, lvl+1); + geniCodeAssign (result, geniCodeRValue (opFalse, FALSE), 0, 0); /* create the exit label */ geniCodeLabel (exitLabel); @@ -2787,13 +3221,13 @@ geniCodeConditional (ast * tree,int lvl) /* 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; @@ -2801,10 +3235,11 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) /* left is integral type and right is literal then check if the literal value is within bounds */ - if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype)) + if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) && + checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL && + !options.lessPedantic) { - checkConstantRange(ltype, - OP_VALUE(right), "= operation", 0); + werror (W_LIT_OVERFLOW); } /* if the left & right type don't exactly match */ @@ -2816,28 +3251,35 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) && compareType (ltype, rtype) <= 0) { - if (compareType (ltype->next, rtype) < 0) - right = geniCodeCast (ltype->next, right, TRUE); + if (left->aggr2ptr) + right = geniCodeCast (ltype, right, TRUE); + else if (compareType (ltype->next, rtype) < 0) + 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; + operand *newRight; 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; + IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0); + /* avoid double fetch from volatile right, see bug 1369874 */ + if (!isOperandVolatile (right, FALSE)) + SPIL_LOC (newRight) = sym; + right = newRight; ADDTOCHAIN (ic); } @@ -2851,13 +3293,33 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) ic->supportRtn = 1; ic->nosupdate = nosupdate; - return left; + /* left could be a pointer assignment, + return the properly casted right instead */ + return right; +} + +/*-----------------------------------------------------------------*/ +/* 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) @@ -2880,20 +3342,20 @@ geniCodeSEParms (ast * parms,int lvl) 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; @@ -2903,14 +3365,14 @@ geniCodeParms (ast * parms, value *argVals, int *stack, 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; } @@ -2923,47 +3385,47 @@ geniCodeParms (ast * parms, value *argVals, int *stack, /* 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; @@ -2979,12 +3441,13 @@ geniCodeCall (operand * left, ast * parms,int lvl) 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 @@ -2992,8 +3455,12 @@ geniCodeCall (operand * left, ast * parms,int lvl) 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)) { @@ -3002,7 +3469,7 @@ geniCodeCall (operand * left, ast * parms,int lvl) 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); @@ -3018,51 +3485,62 @@ geniCodeCall (operand * left, ast * parms,int lvl) /*-----------------------------------------------------------------*/ /* 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; } @@ -3071,12 +3549,13 @@ geniCodeReceive (value * args) /*-----------------------------------------------------------------*/ /* geniCodeFunctionBody - create the function body */ /*-----------------------------------------------------------------*/ -void +void geniCodeFunctionBody (ast * tree,int lvl) { iCode *ic; operand *func; sym_link *fetype; + char *savefilename; int savelineno; /* reset the auto generation */ @@ -3088,21 +3567,26 @@ geniCodeFunctionBody (ast * tree,int lvl) func = ast2iCode (tree->left,lvl+1); fetype = getSpec (operandType (func)); + savefilename = filename; savelineno = lineno; + filename = OP_SYMBOL (func)->fileDef; lineno = OP_SYMBOL (func)->lineDef; /* create an entry label */ geniCodeLabel (entryLabel); + filename = savefilename; lineno = savelineno; /* create a proc icode */ ic = newiCode (FUNCTION, func, NULL); - lineno=ic->lineno = OP_SYMBOL (func)->lineDef; + filename = ic->filename = OP_SYMBOL (func)->fileDef; + 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); @@ -3112,6 +3596,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* now generate the end proc */ ic = newiCode (ENDFUNCTION, func, NULL); + ic->tree = tree; ADDTOCHAIN (ic); return; } @@ -3119,7 +3604,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /*-----------------------------------------------------------------*/ /* geniCodeReturn - gen icode for 'return' statement */ /*-----------------------------------------------------------------*/ -void +void geniCodeReturn (operand * op) { iCode *ic; @@ -3135,7 +3620,7 @@ geniCodeReturn (operand * op) /*-----------------------------------------------------------------*/ /* geniCodeIfx - generates code for extended if statement */ /*-----------------------------------------------------------------*/ -void +void geniCodeIfx (ast * tree,int lvl) { iCode *ic; @@ -3153,37 +3638,35 @@ geniCodeIfx (ast * tree,int lvl) 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); + } 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); } @@ -3194,15 +3677,22 @@ exit: /*-----------------------------------------------------------------*/ /* 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; @@ -3210,66 +3700,131 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* 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) ulFromVal (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) ulFromVal (vch); - /* 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)) + /* 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; + + /* 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) ulFromVal (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) ulFromVal (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), '<', NULL); + ic = newiCodeCondition (boundary, falseLabel, NULL); + ADDTOCHAIN (ic); + } /* now for upper bounds */ - boundary = geniCodeLogic (cond, operandFromLit (max), '>'); + boundary = geniCodeLogic (cond, operandFromLit (max), '>', NULL); ic = newiCodeCondition (boundary, falseLabel, NULL); ADDTOCHAIN (ic); } @@ -3277,8 +3832,9 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* 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 */ @@ -3300,21 +3856,60 @@ geniCodeSwitch (ast * tree,int lvl) 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) ulFromVal (cond->operand.valOperand); + while (caseVals) + { + caseVal = (int) ulFromVal (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, NULL); SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d", - tree->values.switchVals.swNum, - (int) floatFromVal (caseVals)); + tree->values.switchVals.swNum, + (int) ulFromVal (caseVals)); trueLabel = newiTempLabel (buffer); ic = newiCodeCondition (compare, trueLabel, NULL); @@ -3323,15 +3918,15 @@ geniCodeSwitch (ast * tree,int lvl) } - +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); @@ -3344,7 +3939,7 @@ jumpTable: /*-----------------------------------------------------------------*/ /* geniCodeInline - intermediate code for inline assembler */ /*-----------------------------------------------------------------*/ -static void +static void geniCodeInline (ast * tree) { iCode *ic; @@ -3357,7 +3952,7 @@ geniCodeInline (ast * tree) /*-----------------------------------------------------------------*/ /* geniCodeArrayInit - intermediate code for array initializer */ /*-----------------------------------------------------------------*/ -static void +static void geniCodeArrayInit (ast * tree, operand *array) { iCode *ic; @@ -3375,6 +3970,46 @@ geniCodeArrayInit (ast * tree, operand *array) 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 && !TARGET_IS_HC08) + { + 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 */ @@ -3408,7 +4043,7 @@ void delLvaluereq() if(lpItem) Safe_free(lpItem); } /*-----------------------------------------------------------------*/ -/* clearLvaluereq - clear lvalreq flag */ +/* clearLvaluereq - clear lvalreq flag */ /*-----------------------------------------------------------------*/ void clearLvaluereq() { @@ -3417,7 +4052,7 @@ void clearLvaluereq() if(lpItem) lpItem->req = 0; } /*-----------------------------------------------------------------*/ -/* getLvaluereq - get the last lvalreq level */ +/* getLvaluereq - get the last lvalreq level */ /*-----------------------------------------------------------------*/ int getLvaluereqLvl() { @@ -3427,7 +4062,7 @@ int getLvaluereqLvl() return 0; } /*-----------------------------------------------------------------*/ -/* isLvaluereq - is lvalreq valid for this level ? */ +/* isLvaluereq - is lvalreq valid for this level ? */ /*-----------------------------------------------------------------*/ int isLvaluereq(int lvl) { @@ -3457,6 +4092,8 @@ ast2iCode (ast * tree,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); @@ -3469,8 +4106,14 @@ ast2iCode (ast * tree,int lvl) (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; } @@ -3479,11 +4122,14 @@ ast2iCode (ast * tree,int lvl) 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) || @@ -3499,22 +4145,22 @@ ast2iCode (ast * tree,int lvl) 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); } } @@ -3523,153 +4169,188 @@ ast2iCode (ast * tree,int 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)); - case CAST: + 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; + 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 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); + if (!IS_BIT (operandType (op))) + setOperandType (op, UCHARTYPE); + return op; } + case GETABIT: + { + operand *op = geniCodeBinary (geniCodeRValue (left, FALSE), + geniCodeRValue (right, FALSE), + tree->opval.op); + if (!IS_BIT (operandType (op))) + setOperandType (op, UCHARTYPE); + return op; + } + case GETBYTE: + { + operand *op = geniCodeBinary (geniCodeRValue (left, FALSE), + geniCodeRValue (right, FALSE), + tree->opval.op); + setOperandType (op, UCHARTYPE); + return op; + } + case GETWORD: + { + operand *op = geniCodeBinary (geniCodeRValue (left, FALSE), + geniCodeRValue (right, FALSE), + tree->opval.op); + setOperandType (op, UINTTYPE); + 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. + the two calls in a different order. to get the same + result on all machines we have to specify a clear sequence. return geniCodeLogic (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), tree->opval.op); */ { - operand *leftOp, *rightOp; + operand *leftOp, *rightOp; - rightOp = geniCodeRValue (right, FALSE); - leftOp = geniCodeRValue (left , FALSE); + leftOp = geniCodeRValue (left , FALSE); + rightOp = geniCodeRValue (right, FALSE); - return geniCodeLogic (leftOp, rightOp, tree->opval.op); + return geniCodeLogic (leftOp, rightOp, tree->opval.op, tree); } case '?': return geniCodeConditional (tree,lvl); @@ -3679,113 +4360,125 @@ ast2iCode (ast * tree,int 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); + + return geniCodeAssign (left, right, 0, 1); } 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); @@ -3813,10 +4506,13 @@ ast2iCode (ast * tree,int lvl) 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; @@ -3835,7 +4531,7 @@ reverseiCChain () { loop->next = prev; if (prev) - prev->prev = loop; + prev->prev = loop; prev = loop; } @@ -3863,26 +4559,26 @@ static const char *opTypeToStr(OPTYPE op) 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"); - exit(-1); + 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(EXIT_FAILURE); return op; // never reached, makes compiler happy. }