X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.c;h=82199b508d676ffe84bfa90c71380d42533915c0;hb=9998aea306b1018e7c6880e990b3d723f716a021;hp=a7439f0c3c8ac57c073f0e953b057195b26577fd;hpb=6e4a1b4c5f93909af5bc1a15e2fbb0e70189fa5b;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index a7439f0c..82199b50 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -51,6 +51,7 @@ operand *geniCodeArray2Ptr (operand *); operand *geniCodeRValue (operand *, bool); operand *geniCodeDerefPtr (operand *,int); int isLvaluereq(int lvl); +void setOClass (sym_link * ptr, sym_link * spec); #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s) /* forward definition of ic print functions */ @@ -67,6 +68,9 @@ PRINTFUNC (picIfx); PRINTFUNC (picJumpTable); PRINTFUNC (picInline); PRINTFUNC (picReceive); +PRINTFUNC (picDummyRead); +PRINTFUNC (picCritical); +PRINTFUNC (picEndCritical); iCodeTable codeTable[] = { @@ -113,12 +117,16 @@ iCodeTable codeTable[] = {RECEIVE, "recv", picReceive, NULL}, {SEND, "send", picGenericOne, NULL}, {ARRAYINIT, "arrayInit", picGenericOne, NULL}, + {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}, + {CRITICAL, "critical_start", picCritical, NULL}, + {ENDCRITICAL, "critical_end", picEndCritical, NULL} }; /*-----------------------------------------------------------------*/ /* checkConstantRange: check a constant against the type */ /*-----------------------------------------------------------------*/ + /* pedantic=0: allmost anything is allowed as long as the absolute value is within the bit range of the type, and -1 is treated as 0xf..f for unsigned types (e.g. in assign) @@ -126,9 +134,9 @@ iCodeTable codeTable[] = pedantic>1: "char c=200" is not allowed (evaluates to -56) */ -void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) { +void checkConstantRange(sym_link *ltype, value *val, char *msg, + int pedantic) { double max; - char message[132]=""; int warnings=0; int negative=0; long v; @@ -178,8 +186,9 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) { warnings++; } +#if 0 // temporary disabled, leaving the warning as a reminder if (warnings) { - sprintf (message, "for %s %s in %s", + SNPRINTF (message, sizeof(message), "for %s %s in %s", SPEC_USIGN(ltype) ? "unsigned" : "signed", nounName(ltype), msg); werror (W_CONST_RANGE, message); @@ -187,6 +196,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) { if (pedantic>1) fatalError++; } +#endif } /*-----------------------------------------------------------------*/ @@ -214,7 +224,7 @@ printOperand (operand * op, FILE * file) if (SPEC_NOUN (opetype) == V_FLOAT) fprintf (file, "%g {", SPEC_CVAL (opetype).v_float); else - fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand)); + fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand)); printTypeChain (operandType (op), file); fprintf (file, "}"); break; @@ -222,12 +232,14 @@ printOperand (operand * op, FILE * file) 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}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */ + 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->isaddr, OP_SYMBOL (op)->isreqv, + OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc, + OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr ); { fprintf (file, "{"); @@ -382,6 +394,9 @@ PRINTFUNC (picGenericOne) if (!IC_RESULT (ic) && !IC_LEFT (ic)) fprintf (of, s); + if (ic->op == SEND || ic->op == RECEIVE) { + fprintf(of,"{argreg = %d}",ic->argreg); + } fprintf (of, "\n"); } @@ -454,10 +469,40 @@ PRINTFUNC (picReceive) fprintf (of, "\n"); } +PRINTFUNC (picDummyRead) +{ + fprintf (of, "\t"); + fprintf (of, "%s ", s); + printOperand (IC_RIGHT (ic), of); + fprintf (of, "\n"); +} + +PRINTFUNC (picCritical) +{ + fprintf (of, "\t"); + if (IC_RESULT (ic)) + printOperand (IC_RESULT (ic), of); + else + fprintf (of, "(stack)"); + fprintf (of, " = %s ", s); + fprintf (of, "\n"); +} + +PRINTFUNC (picEndCritical) +{ + fprintf (of, "\t"); + fprintf (of, "%s = ", s); + if (IC_RIGHT (ic)) + printOperand (IC_RIGHT (ic), of); + else + fprintf (of, "(stack)"); + fprintf (of, "\n"); +} + /*-----------------------------------------------------------------*/ /* piCode - prints one iCode */ /*-----------------------------------------------------------------*/ -int +int piCode (void *item, FILE * of) { iCode *ic = item; @@ -481,7 +526,7 @@ void PICC(iCode *ic) /*-----------------------------------------------------------------*/ /* printiCChain - prints intermediate code for humans */ /*-----------------------------------------------------------------*/ -void +void printiCChain (iCode * icChain, FILE * of) { iCode *loop; @@ -493,7 +538,7 @@ printiCChain (iCode * icChain, FILE * of) { if ((icTab = getTableEntry (loop->op))) { - fprintf (of, "%s(%d:%d:%d:%d:%d)\t", + 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); @@ -570,7 +615,7 @@ newiCodeLabelGoto (int op, symbol * label) ic = newiCode (op, NULL, NULL); ic->op = op; - ic->argLabel.label = label; + ic->label = label; IC_LEFT (ic) = NULL; IC_RIGHT (ic) = NULL; IC_RESULT (ic) = NULL; @@ -586,11 +631,16 @@ newiTemp (char *s) symbol *itmp; if (s) - sprintf (buffer, "%s", s); + { + SNPRINTF (buffer, sizeof(buffer), "%s", s); + } else - sprintf (buffer, "iTemp%d", iTempNum++); + { + SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++); + } + itmp = newSymbol (buffer, 1); - strcpy (itmp->rname, itmp->name); + strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX); itmp->isitmp = 1; return itmp; @@ -609,10 +659,12 @@ newiTempLabel (char *s) return itmplbl; if (s) - itmplbl = newSymbol (s, 1); + { + itmplbl = newSymbol (s, 1); + } else { - sprintf (buffer, "iTempLbl%d", iTempLblNum++); + SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++); itmplbl = newSymbol (buffer, 1); } @@ -631,7 +683,7 @@ newiTempPreheaderLabel () { symbol *itmplbl; - sprintf (buffer, "preHeaderLbl%d", iTempLblNum++); + SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++); itmplbl = newSymbol (buffer, 1); itmplbl->isitmp = 1; @@ -683,7 +735,6 @@ copyiCode (iCode * ic) case PCALL: IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic)); IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic)); - IC_ARGS (nic) = IC_ARGS (ic); break; case INLINEASM: @@ -709,7 +760,7 @@ copyiCode (iCode * ic) iCodeTable * getTableEntry (int oper) { - int i; + unsigned i; for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++) if (oper == codeTable[i].icode) @@ -786,6 +837,8 @@ isParameterToCall (value * args, operand * op) { value *tval = args; + wassert (IS_SYMOP(op)); + while (tval) { if (tval->sym && @@ -808,7 +861,7 @@ isOperandGlobal (operand * op) if (IS_ITEMP (op)) return 0; - if (op->type == SYMBOL && + if (IS_SYMOP(op) && (op->operand.symOperand->level == 0 || IS_STATIC (op->operand.symOperand->etype) || IS_EXTERN (op->operand.symOperand->etype)) @@ -831,13 +884,13 @@ 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; } /*-----------------------------------------------------------------*/ @@ -858,6 +911,7 @@ isOperandLiteral (operand * op) return 0; } + /*-----------------------------------------------------------------*/ /* isOperandInFarSpace - will return true if operand is in farSpace */ /*-----------------------------------------------------------------*/ @@ -886,6 +940,64 @@ isOperandInFarSpace (operand * op) return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE); } +/*------------------------------------------------------------------*/ +/* isOperandInDirSpace - will return true if operand is in dirSpace */ +/*------------------------------------------------------------------*/ +bool +isOperandInDirSpace (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_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE); +} + +/*--------------------------------------------------------------------*/ +/* isOperandInCodeSpace - will return true if operand is in codeSpace */ +/*--------------------------------------------------------------------*/ +bool +isOperandInCodeSpace (operand * op) +{ + sym_link *etype; + + if (!op) + return FALSE; + + if (!IS_SYMOP (op)) + return FALSE; + + etype = getSpec (operandType (op)); + + if (!IS_TRUE_SYMOP (op)) + { + if (SPIL_LOC (op)) + etype = SPIL_LOC (op)->etype; + else + return FALSE; + } + else + { + etype = getSpec (operandType (op)); + } + return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE); +} + /*-----------------------------------------------------------------*/ /* isOperandOnStack - will return true if operand is on stack */ /*-----------------------------------------------------------------*/ @@ -901,14 +1013,18 @@ isOperandOnStack (operand * op) return FALSE; etype = getSpec (operandType (op)); + if (IN_STACK (etype) || + OP_SYMBOL(op)->onStack || + (SPIL_LOC(op) && SPIL_LOC(op)->onStack)) + return TRUE; - return ((IN_STACK (etype)) ? TRUE : FALSE); + return FALSE; } /*-----------------------------------------------------------------*/ /* operandLitValue - literal value of an operand */ /*-----------------------------------------------------------------*/ -double +double operandLitValue (operand * op) { assert (isOperandLiteral (op)); @@ -917,7 +1033,32 @@ operandLitValue (operand * op) } /*-----------------------------------------------------------------*/ -/* operandOperation - perforoms operations on operands */ +/* getBuiltInParms - returns parameters to a builtin functions */ +/*-----------------------------------------------------------------*/ +iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms) +{ + sym_link *ftype; + + *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)++; + } + + ic->generated = 1; + /* make sure this is a builtin function call */ + assert(IS_SYMOP(IC_LEFT(ic))); + ftype = operandType(IC_LEFT(ic)); + assert(IFFUNC_ISBUILTIN(ftype)); + return ic; +} + +/*-----------------------------------------------------------------*/ +/* operandOperation - performs operations on operands */ /*-----------------------------------------------------------------*/ operand * operandOperation (operand * left, operand * right, @@ -925,12 +1066,12 @@ operandOperation (operand * left, operand * right, { sym_link *let , *ret=NULL; operand *retval = (operand *) 0; - + assert (isOperandLiteral (left)); let = getSpec(operandType(left)); if (right) { assert (isOperandLiteral (right)); - ret = getSpec(operandType(left)); + ret = getSpec(operandType(right)); } switch (op) @@ -946,12 +1087,61 @@ operandOperation (operand * left, operand * right, operandLitValue (right))); break; case '*': + /* retval = operandFromValue (valCastLiteral (type, operandLitValue (left) * operandLitValue (right))); + This could be all we've to do, but with gcc we've to take care about + overflows. Two examples: + ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least + significant bits are lost (52 in fraction, 63 bits would be + necessary to keep full precision). + If the resulting double value is greater than ULONG_MAX (resp. + USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)! + */ + + /* if it is not a specifier then we can assume that */ + /* it will be an unsigned long */ + if (IS_INT (type) || + !IS_SPEC (type)) + { + /* long is handled here, because it can overflow with double */ + if (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 (ul != (TYPE_UWORD) ul) + werror (W_INT_OVL); + } + else /* signed int */ + { + /* signed int is handled here in order to detect overflow */ + TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) * + (TYPE_WORD) operandLitValue (right); + + retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l)); + if (l != (TYPE_WORD) l) + werror (W_INT_OVL); + } + } + else + /* all others go here: */ + retval = operandFromValue (valCastLiteral (type, + operandLitValue (left) * + operandLitValue (right))); break; case '/': - if ((unsigned long) operandLitValue (right) == 0) + if ((TYPE_UDWORD) operandLitValue (right) == 0) { werror (E_DIVIDE_BY_ZERO); retval = right; @@ -963,38 +1153,57 @@ operandOperation (operand * left, operand * right, operandLitValue (right))); break; case '%': - if ((unsigned long) operandLitValue (right) == 0) { + if ((TYPE_UDWORD) operandLitValue (right) == 0) { werror (E_DIVIDE_BY_ZERO); retval = right; } - else - retval = operandFromLit ((SPEC_USIGN(let) ? - (unsigned long) operandLitValue (left) : - (long) operandLitValue (left)) % - (SPEC_USIGN(ret) ? - (unsigned long) operandLitValue (right) : - (long) operandLitValue (right))); - + 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)); + } break; case LEFT_OP: - retval = operandFromLit ((SPEC_USIGN(let) ? - (unsigned long) operandLitValue (left) : - (long) operandLitValue (left)) << - (SPEC_USIGN(ret) ? - (unsigned long) operandLitValue (right) : - (long) operandLitValue (right))); + /* The number of left shifts is always unsigned. Signed doesn't make + sense here. Shifting by a negative number is impossible. */ + retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) << + (TYPE_UDWORD) operandLitValue (right)); break; case RIGHT_OP: - retval = operandFromLit ((SPEC_USIGN(let) ? - (unsigned long) operandLitValue (left) : - (long) operandLitValue (left)) >> - (SPEC_USIGN(ret) ? - (unsigned long) operandLitValue (right) : - (long) operandLitValue (right))); + /* The number of right shifts is always unsigned. Signed doesn't make + sense here. Shifting by a negative number is impossible. */ + if (SPEC_USIGN(let)) + /* unsigned: logic shift right */ + retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >> + (TYPE_UDWORD) operandLitValue (right)); + else + /* signed: arithmetic shift right */ + retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >> + (TYPE_UDWORD) operandLitValue (right)); break; case EQ_OP: - retval = operandFromLit (operandLitValue (left) == - operandLitValue (right)); + /* 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); + } break; case '<': retval = operandFromLit (operandLitValue (left) < @@ -1017,16 +1226,19 @@ operandOperation (operand * left, operand * right, operandLitValue (right)); break; case BITWISEAND: - retval = operandFromLit ((long)operandLitValue(left) & - (long)operandLitValue(right)); + retval = operandFromValue (valCastLiteral (type, + (TYPE_UDWORD)operandLitValue(left) & + (TYPE_UDWORD)operandLitValue(right))); break; case '|': - retval = operandFromLit ((long)operandLitValue (left) | - (long)operandLitValue (right)); + retval = operandFromValue (valCastLiteral (type, + (TYPE_UDWORD)operandLitValue(left) | + (TYPE_UDWORD)operandLitValue(right))); break; case '^': - retval = operandFromLit ((long)operandLitValue (left) ^ - (long)operandLitValue (right)); + retval = operandFromValue (valCastLiteral (type, + (TYPE_UDWORD)operandLitValue(left) ^ + (TYPE_UDWORD)operandLitValue(right))); break; case AND_OP: retval = operandFromLit (operandLitValue (left) && @@ -1038,7 +1250,7 @@ operandOperation (operand * left, operand * right, break; case RRC: { - long i = (long) operandLitValue (left); + TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left); retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) | (i << 1)); @@ -1046,7 +1258,7 @@ operandOperation (operand * left, operand * right, break; case RLC: { - long i = (long) operandLitValue (left); + TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left); retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) | (i >> 1)); @@ -1054,11 +1266,12 @@ operandOperation (operand * left, operand * right, break; case UNARYMINUS: - retval = operandFromLit (-1 * operandLitValue (left)); + retval = operandFromValue (valCastLiteral (type, + -1 * operandLitValue (left))); break; case '~': - retval = operandFromLit (~((long) operandLitValue (left))); + retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left))); break; case '!': @@ -1078,7 +1291,7 @@ operandOperation (operand * left, operand * right, /*-----------------------------------------------------------------*/ /* isOperandEqual - compares two operand & return 1 if they r = */ /*-----------------------------------------------------------------*/ -int +int isOperandEqual (operand * left, operand * right) { /* if the pointers are equal then they are equal */ @@ -1266,7 +1479,6 @@ 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_DS390)) && */ (!(options.model == MODEL_FLAT24)) ) && options.stackAuto == 0) ok = 0; @@ -1276,14 +1488,14 @@ operandFromSymbol (symbol * sym) !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 register euivalence */ + !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 */ ) - { + { /* we will use it after all optimizations and before liveRange calculation */ @@ -1292,6 +1504,7 @@ operandFromSymbol (symbol * sym) OP_SYMBOL (sym->reqv)->key = sym->key; OP_SYMBOL (sym->reqv)->isreqv = 1; OP_SYMBOL (sym->reqv)->islocal = 1; + OP_SYMBOL (sym->reqv)->onStack = sym->onStack; SPIL_LOC (sym->reqv) = sym; } @@ -1330,8 +1543,6 @@ operandFromSymbol (symbol * sym) else IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type)); - IC_RESULT (ic)->operand.symOperand->args = sym->args; - ADDTOCHAIN (ic); return IC_RESULT (ic); @@ -1407,10 +1618,13 @@ operandFromAst (ast * tree,int lvl) case EX_LINK: return operandFromLink (tree->opval.lnk); - } + break; - assert (0); - /* Just to keep the comiler happy */ + default: + assert (0); + } + + /* Just to keep the compiler happy */ return (operand *) 0; } @@ -1512,6 +1726,7 @@ usualBinaryConversions (operand ** op1, operand ** op2) sym_link *ltype = operandType (*op1); ctype = computeType (ltype, rtype); + *op1 = geniCodeCast (ctype, *op1, TRUE); *op2 = geniCodeCast (ctype, *op2, TRUE); @@ -1553,7 +1768,6 @@ geniCodeRValue (operand * op, bool force) if (IS_SPEC (type) && IS_TRUE_SYMOP (op) && (!IN_FARSPACE (SPEC_OCLS (etype)) || - /* TARGET_IS_DS390)) */ (options.model == MODEL_FLAT24) )) { op = operandFromOperand (op); @@ -1572,10 +1786,6 @@ geniCodeRValue (operand * op, bool force) /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */ - /* if the right is a symbol */ - if (op->type == SYMBOL) - IC_RESULT (ic)->operand.symOperand->args = - op->operand.symOperand->args; ADDTOCHAIN (ic); return IC_RESULT (ic); @@ -1613,9 +1823,9 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) 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. + // 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)) { + 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); @@ -1638,7 +1848,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) } } } else { // from a pointer to a pointer - if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) { + 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 @@ -1664,13 +1874,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) } } if (errors) { - /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name, - implicit?"(implicit)":"", errors); */ - fprintf (stderr, "from type '"); - printTypeChain (optype, stderr); - fprintf (stderr, "' to type '"); - printTypeChain (type, stderr); - fprintf (stderr, "'\n"); + printFromToType (optype, type); } /* if they are the same size create an assignment */ @@ -1699,7 +1903,8 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /* preserve the storage class & output class */ /* of the original variable */ restype = getSpec (operandType (IC_RESULT (ic))); - SPEC_SCLS (restype) = SPEC_SCLS (opetype); + if (!IS_LITERAL(opetype)) + SPEC_SCLS (restype) = SPEC_SCLS (opetype); SPEC_OCLS (restype) = SPEC_OCLS (opetype); ADDTOCHAIN (ic); @@ -1764,11 +1969,11 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) /* if the right is a literal & power of 2 */ /* then make it a left shift */ - /* code generated for 1 byte * 1 byte literal = 2 bytes result is more - efficient in most cases than 2 bytes result = 2 bytes << literal + /* code generated for 1 byte * 1 byte literal = 2 bytes result is more + efficient in most cases than 2 bytes result = 2 bytes << literal if port has 1 byte muldiv */ if (p2 && !IS_FLOAT (letype) && - !((resultIsInt) && (getSize (resType) != getSize (ltype)) && + !((resultIsInt) && (getSize (resType) != getSize (ltype)) && (port->support.muldiv == 1))) { if ((resultIsInt) && (getSize (resType) != getSize (ltype))) @@ -1809,10 +2014,12 @@ geniCodeDivision (operand * left, operand * right) resType = usualBinaryConversions (&left, &right); - /* if the right is a literal & power of 2 */ - /* then make it a right shift */ + /* 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)))) { ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */ @@ -1882,6 +2089,11 @@ geniCodePtrPtrSubtract (operand * left, operand * right) ADDTOCHAIN (ic); subtractExit: + if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) { + return result; + } + + // should we really do this? is this ANSI? return geniCodeDivision (result, operandFromLit (getSize (ltype->next))); } @@ -1938,7 +2150,7 @@ geniCodeSubtract (operand * left, operand * right) /* geniCodeAdd - generates iCode for addition */ /*-----------------------------------------------------------------*/ operand * -geniCodeAdd (operand * left, operand * right,int lvl) +geniCodeAdd (operand * left, operand * right, int lvl) { iCode *ic; sym_link *resType; @@ -1946,10 +2158,6 @@ geniCodeAdd (operand * left, operand * right,int lvl) int isarray = 0; LRTYPE; - /* if left is an array then array access */ - if (IS_ARRAY (ltype)) - return geniCodeArray (left, right,lvl); - /* if the right side is LITERAL zero */ /* return the left side */ if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype))) @@ -1959,8 +2167,8 @@ geniCodeAdd (operand * left, operand * right,int lvl) if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype))) return right; - /* if left is an array or pointer then size */ - if (IS_PTR (ltype)) + /* if left is a pointer then size */ + if (IS_PTR (ltype) || IS_ARRAY(ltype)) { isarray = left->isaddr; // there is no need to multiply with 1 @@ -1971,7 +2179,7 @@ geniCodeAdd (operand * left, operand * right,int lvl) resType = copyLinkChain (ltype); } else - { /* make them the same size */ + { // make them the same size resType = usualBinaryConversions (&left, &right); } @@ -2006,26 +2214,16 @@ aggrToPtr (sym_link * type, bool force) sym_link *etype; sym_link *ptype; - if (IS_PTR (type) && !force) return type; etype = getSpec (type); - ptype = newLink (); + ptype = newLink (DECLARATOR); ptype->next = type; - /* if the output class is generic */ - if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER) - DCL_PTR_CONST (ptype) = port->mem.code_ro; - - /* if the variable was declared a constant */ - /* then the pointer points to a constant */ - if (IS_CONSTANT (etype)) - DCL_PTR_CONST (ptype) = 1; - - /* the variable was volatile then pointer to volatile */ - if (IS_VOLATILE (etype)) - DCL_PTR_VOLATILE (ptype) = 1; + + /* set the pointer depending on the storage class */ + DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype)); return ptype; } @@ -2039,18 +2237,8 @@ geniCodeArray2Ptr (operand * 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; + DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype)); - /* the variable was volatile then pointer to volatile */ - if (IS_VOLATILE (opetype)) - DCL_PTR_VOLATILE (optype) = 1; op->isaddr = 0; return op; } @@ -2064,14 +2252,14 @@ geniCodeArray (operand * left, operand * right,int lvl) { iCode *ic; sym_link *ltype = operandType (left); - + if (IS_PTR (ltype)) { if (IS_PTR (ltype->next) && left->isaddr) { left = geniCodeRValue (left, FALSE); } - return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl); + return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl); } right = geniCodeMultiply (right, @@ -2096,6 +2284,7 @@ geniCodeArray (operand * left, operand * right,int lvl) IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next)); ADDTOCHAIN (ic); + return IC_RESULT (ic); } @@ -2112,6 +2301,8 @@ geniCodeStruct (operand * left, operand * right, bool islval) symbol *element = getStructElement (SPEC_STRUCT (etype), right->operand.symOperand); + wassert(IS_SYMOP(right)); + /* add the offset */ ic = newiCode ('+', left, operandFromLit (element->offset)); @@ -2123,13 +2314,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)); } @@ -2184,7 +2375,7 @@ geniCodePostInc (operand * op) /* geniCodePreInc - generate code for preIncrement */ /*-----------------------------------------------------------------*/ operand * -geniCodePreInc (operand * op) +geniCodePreInc (operand * op, bool lvalue) { iCode *ic; sym_link *optype = operandType (op); @@ -2210,8 +2401,11 @@ geniCodePreInc (operand * op) IC_RESULT (ic) = result = newiTempOperand (roptype, 0); ADDTOCHAIN (ic); - - return geniCodeAssign (op, result, 0); + (void) geniCodeAssign (op, result, 0); + if (lvalue) + return op; + else + return result; } /*-----------------------------------------------------------------*/ @@ -2264,7 +2458,7 @@ 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); @@ -2290,8 +2484,11 @@ geniCodePreDec (operand * op) IC_RESULT (ic) = result = newiTempOperand (roptype, 0); ADDTOCHAIN (ic); - - return geniCodeAssign (op, result, 0); + (void) geniCodeAssign (op, result, 0); + if (lvalue) + return op; + else + return result; } @@ -2332,19 +2529,10 @@ geniCodeAddressOf (operand * op) /* return op; */ /* } */ - p = newLink (); - p->class = DECLARATOR; + 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); @@ -2414,16 +2602,19 @@ geniCodeDerefPtr (operand * op,int lvl) sym_link *rtype, *retype; sym_link *optype = operandType (op); - /* if this is a pointer then generate the rvalue */ - if (IS_PTR (optype)) + // if this is an array then array access + if (IS_ARRAY (optype)) { + // don't worry, this will be optimized out later + return geniCodeArray (op, operandFromLit (0), lvl); + } + + // just in case someone screws up + wassert (IS_PTR (optype)); + + if (IS_TRUE_SYMOP (op)) { - if (IS_TRUE_SYMOP (op)) - { - op->isaddr = 1; - op = geniCodeRValue (op, TRUE); - } - else - op = geniCodeRValue (op, TRUE); + op->isaddr = 1; + op = geniCodeRValue (op, TRUE); } /* now get rid of the pointer part */ @@ -2434,19 +2625,12 @@ geniCodeDerefPtr (operand * op,int lvl) else { retype = getSpec (rtype = copyLinkChain (optype->next)); + /* outputclass needs 2b updated */ + setOClass (optype, retype); } - - /* if this is a pointer then outputclass needs 2b updated */ - if (IS_PTR (optype)) - setOClass (optype, retype); - + op->isGptr = IS_GENPTR (optype); - /* if the pointer was declared as a constant */ - /* then we cannot allow assignment to the derefed */ - if (IS_PTR_CONST (optype)) - SPEC_CONST (retype) = 1; - op->isaddr = (IS_PTR (rtype) || IS_STRUCT (rtype) || IS_INT (rtype) || @@ -2522,10 +2706,53 @@ 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, + checkConstantRange(ltype, OP_VALUE(right), "compare operation", 1); } + /* if one operand is a pointer and the other is a literal generic void pointer, + change the type of the literal generic void pointer to match the other pointer */ + if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left) + && IS_PTR (rtype) && !IS_GENPTR(rtype)) + { + /* find left's definition */ + ic = (iCode *) setFirstItem (iCodeChain); + while (ic) + { + if (((ic->op == CAST) || (ic->op == '=')) + && isOperandEqual(left, IC_RESULT (ic))) + break; + else + ic = setNextItem (iCodeChain); + } + /* if casting literal to generic pointer, then cast to rtype instead */ + if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) + { + left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic)))); + ltype = operandType(left); + } + } + if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right) + && IS_PTR (ltype) && !IS_GENPTR(ltype)) + { + /* find right's definition */ + ic = (iCode *) setFirstItem (iCodeChain); + while (ic) + { + if (((ic->op == CAST) || (ic->op == '=')) + && isOperandEqual(right, IC_RESULT (ic))) + break; + else + ic = setNextItem (iCodeChain); + } + /* if casting literal to generic pointer, then cast to rtype instead */ + if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) + { + right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic)))); + rtype = operandType(right); + } + } + ctype = usualBinaryConversions (&left, &right); ic = newiCode (op, left, right); @@ -2577,7 +2804,7 @@ geniCodeConditional (ast * tree,int lvl) true = ast2iCode (tree->right->left,lvl+1); /* move the value to a new Operand */ - result = newiTempOperand (operandType (true), 0); + result = newiTempOperand (tree->right->ftype, 0); geniCodeAssign (result, geniCodeRValue (true, FALSE), 0); /* generate an unconditional goto */ @@ -2626,7 +2853,7 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) /* first check the type for pointer assignement */ if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) && - compareType (ltype, rtype) < 0) + compareType (ltype, rtype) <= 0) { if (compareType (ltype->next, rtype) < 0) right = geniCodeCast (ltype->next, right, TRUE); @@ -2666,6 +2893,24 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) return left; } +/*-----------------------------------------------------------------*/ +/* geniCodeDummyRead - generate code for dummy read */ +/*-----------------------------------------------------------------*/ +static void +geniCodeDummyRead (operand * op) +{ + iCode *ic; + sym_link *type = operandType (op); + + if (!IS_VOLATILE(type)) + return; + + ic = newiCode (DUMMY_READ_VOLATILE, NULL, op); + ADDTOCHAIN (ic); + + ic->nosupdate = 1; +} + /*-----------------------------------------------------------------*/ /* geniCodeSEParms - generate code for side effecting fcalls */ /*-----------------------------------------------------------------*/ @@ -2692,30 +2937,38 @@ 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); } /*-----------------------------------------------------------------*/ /* geniCodeParms - generates parameters */ /*-----------------------------------------------------------------*/ -static void -geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl) +value * +geniCodeParms (ast * parms, value *argVals, int *stack, + sym_link * fetype, symbol * func,int lvl) { iCode *ic; operand *pval; if (!parms) - return; + return argVals; + + if (argVals==NULL) { + // first argument + argVals=FUNC_ARGS(func->type); + } /* if this is a param node then do the left & right */ if (parms->type == EX_OP && parms->opval.op == PARAM) { - geniCodeParms (parms->left, stack, fetype, func,lvl); - geniCodeParms (parms->right, stack, fetype, func,lvl); - return; + argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl); + argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl); + return argVals; } /* get the parameter value */ @@ -2738,20 +2991,24 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl } /* if register parm then make it a send */ - if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) || - IS_REGPARM (parms->etype)) && !func->hasVargs) + if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) || + IFFUNC_ISBUILTIN(func->type)) { ic = newiCode (SEND, pval, NULL); + ic->argreg = SPEC_ARGREG(parms->etype); + ic->builtinSEND = FUNC_ISBUILTIN(func->type); ADDTOCHAIN (ic); } else { /* now decide whether to push or assign */ - if (!(options.stackAuto || IS_RENT (fetype))) + if (!(options.stackAuto || IFFUNC_ISREENT (func->type))) { /* assign */ - operand *top = operandFromSymbol (parms->argSym); + 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); } else @@ -2766,6 +3023,8 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl } } + argVals=argVals->next; + return argVals; } /*-----------------------------------------------------------------*/ @@ -2791,15 +3050,15 @@ geniCodeCall (operand * left, ast * parms,int lvl) geniCodeSEParms (parms,lvl); /* first the parameters */ - geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl); + geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl); /* now call : if symbol then pcall */ - if (IS_OP_POINTER (left) || IS_ITEMP(left)) + if (IS_OP_POINTER (left) || IS_ITEMP(left)) { ic = newiCode (PCALL, left, NULL); - else + } else { ic = newiCode (CALL, left, NULL); + } - IC_ARGS (ic) = left->operand.symOperand->args; type = copyLinkChain (operandType (left)->next); etype = getSpec (type); SPEC_EXTR (etype) = 0; @@ -2822,7 +3081,7 @@ geniCodeReceive (value * args) /* for all arguments that are passed in registers */ while (args) { - + int first = 1; if (IS_REGPARM (args->etype)) { operand *opr = operandFromValue (args); @@ -2837,7 +3096,6 @@ geniCodeReceive (value * args) if (IN_FARSPACE (SPEC_OCLS (sym->etype)) && options.stackAuto == 0 && - /* !TARGET_IS_DS390) */ (!(options.model == MODEL_FLAT24)) ) { } @@ -2853,8 +3111,12 @@ geniCodeReceive (value * args) } } - ic = newiCode (RECEIVE, NULL, NULL); - currFunc->recvSize = getSize (sym->etype); + 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); } @@ -2891,10 +3153,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* create a proc icode */ ic = newiCode (FUNCTION, func, NULL); - /* if the function has parmas then */ - /* save the parameters information */ - ic->argLabel.args = tree->values.args; - ic->lineno = OP_SYMBOL (func)->lineDef; + lineno=ic->lineno = OP_SYMBOL (func)->lineDef; ADDTOCHAIN (ic); @@ -2955,14 +3214,14 @@ geniCodeIfx (ast * tree,int lvl) if (tree->trueLabel) geniCodeGoto (tree->trueLabel); else - assert (1); + assert (0); } else { if (tree->falseLabel) geniCodeGoto (tree->falseLabel); else - assert (1); + assert (0); } goto exit; } @@ -3001,6 +3260,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) operand *boundary; symbol *falseLabel; set *labels = NULL; + int needRangeCheck = !optimize.noJTabBoundary + || tree->values.switchVals.swDefault; if (!tree || !caseVals) return 0; @@ -3009,7 +3270,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* all integer numbers between the maximum & minimum must */ /* be present , the maximum value should not exceed 255 */ min = max = (int) floatFromVal (vch = caseVals); - sprintf (buffer, "_case_%d_%d", + SNPRINTF (buffer, sizeof(buffer), + "_case_%d_%d", tree->values.switchVals.swNum, min); addSet (&labels, newiTempLabel (buffer)); @@ -3022,7 +3284,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) { if (((t = (int) floatFromVal (vch)) - max) != 1) return 0; - sprintf (buffer, "_case_%d_%d", + SNPRINTF (buffer, sizeof(buffer), + "_case_%d_%d", tree->values.switchVals.swNum, t); addSet (&labels, newiTempLabel (buffer)); @@ -3034,20 +3297,25 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* 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)) + if ((needRangeCheck && cnt <= 2) || max > (255 / 3)) return 0; if (tree->values.switchVals.swDefault) - sprintf (buffer, "_default_%d", tree->values.switchVals.swNum); + { + SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum); + } else - sprintf (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 */ /* 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 @@ -3069,7 +3337,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) if (min) { cond = geniCodeSubtract (cond, operandFromLit (min)); - setOperandType (cond, UCHARTYPE); + if (!IS_LITERAL(getSpec(operandType(cond)))) + setOperandType (cond, UCHARTYPE); } /* now create the jumptable */ @@ -3083,13 +3352,36 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /*-----------------------------------------------------------------*/ /* geniCodeSwitch - changes a switch to a if statement */ /*-----------------------------------------------------------------*/ -void +void geniCodeSwitch (ast * tree,int lvl) { iCode *ic; operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE); value *caseVals = tree->values.switchVals.swVals; symbol *trueLabel, *falseLabel; + + /* If the condition is a literal, then just jump to the */ + /* appropriate case label. */ + if (IS_LITERAL(getSpec(operandType(cond)))) + { + int switchVal, caseVal; + + switchVal = (int) floatFromVal (cond->operand.valOperand); + while (caseVals) + { + caseVal = (int) floatFromVal (caseVals); + if (caseVal == switchVal) + { + SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d", + tree->values.switchVals.swNum, caseVal); + trueLabel = newiTempLabel (buffer); + geniCodeGoto (trueLabel); + goto jumpTable; + } + caseVals = caseVals->next; + } + goto defaultOrBreak; + } /* if we can make this a jump table */ if (geniCodeJumpTable (cond, caseVals, tree)) @@ -3103,7 +3395,7 @@ geniCodeSwitch (ast * tree,int lvl) operandFromValue (caseVals), EQ_OP); - sprintf (buffer, "_case_%d_%d", + SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d", tree->values.switchVals.swNum, (int) floatFromVal (caseVals)); trueLabel = newiTempLabel (buffer); @@ -3114,12 +3406,16 @@ geniCodeSwitch (ast * tree,int lvl) } - +defaultOrBreak: /* if default is present then goto break else break */ if (tree->values.switchVals.swDefault) - sprintf (buffer, "_default_%d", tree->values.switchVals.swNum); + { + SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum); + } else - sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum); + { + SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum); + } falseLabel = newiTempLabel (buffer); geniCodeGoto (falseLabel); @@ -3161,6 +3457,34 @@ 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; + + /* 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 & disabled */ + 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 */ @@ -3234,6 +3558,7 @@ ast2iCode (ast * tree,int lvl) operand *right = NULL; if (!tree) return NULL; + /* set the global variables for filename & line number */ if (tree->filename) filename = tree->filename; @@ -3255,8 +3580,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; } @@ -3269,7 +3600,8 @@ ast2iCode (ast * tree,int lvl) 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) || @@ -3342,13 +3674,13 @@ ast2iCode (ast * tree,int lvl) if (left) return geniCodePostInc (left); else - return geniCodePreInc (right); + return geniCodePreInc (right, tree->lvalue); case DEC_OP: /* decrement operator */ if (left) return geniCodePostDec (left); else - return geniCodePreDec (right); + return geniCodePreDec (right, tree->lvalue); case '&': /* bitwise and or address of operator */ if (right) @@ -3402,16 +3734,32 @@ ast2iCode (ast * tree,int lvl) case RIGHT_OP: return geniCodeRightShift (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE)); - case CAST: + case CAST: +#if 0 // this indeed needs a second thought + { + operand *op; + + // let's keep this simple: get the rvalue we need + op=geniCodeRValue (right, FALSE); + // now cast it to whatever we want + op=geniCodeCast (operandType(left), op, FALSE); + // if this is going to be used as an lvalue, make it so + if (tree->lvalue) { + op->isaddr=1; + } + return op; + } +#else // bug #604575, is it a bug ???? return geniCodeCast (operandType (left), geniCodeRValue (right, FALSE), FALSE); +#endif case '~': - case '!': case RRC: case RLC: return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op); + case '!': case GETHBIT: { operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op); @@ -3426,9 +3774,21 @@ ast2iCode (ast * tree,int lvl) case NE_OP: case AND_OP: case OR_OP: + /* different compilers (even different gccs) evaluate + the two calls in a different order. to get the same + result on all machines we've to specify a clear sequence. return geniCodeLogic (geniCodeRValue (left, FALSE), - geniCodeRValue (right, FALSE), - tree->opval.op); + geniCodeRValue (right, FALSE), + tree->opval.op); + */ + { + operand *leftOp, *rightOp; + + rightOp = geniCodeRValue (right, FALSE); + leftOp = geniCodeRValue (left , FALSE); + + return geniCodeLogic (leftOp, rightOp, tree->opval.op); + } case '?': return geniCodeConditional (tree,lvl); @@ -3575,6 +3935,9 @@ ast2iCode (ast * tree,int lvl) case ARRAYINIT: geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1)); return NULL; + + case CRITICAL: + geniCodeCritical (tree, lvl); } return NULL; @@ -3612,3 +3975,35 @@ iCodeFromAst (ast * tree) ast2iCode (tree,0); return reverseiCChain (); } + +static const char *opTypeToStr(OPTYPE op) +{ + switch(op) + { + case SYMBOL: return "symbol"; + case VALUE: return "value"; + case TYPE: return "type"; + } + return "undefined type"; +} + + +operand *validateOpType(operand *op, + const char *macro, + const char *args, + OPTYPE type, + const char *file, + unsigned line) +{ + if (op && op->type == type) + { + 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); + return op; // never reached, makes compiler happy. +}