X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.c;h=b989c88dd6fd79ab1e2724fc72971947bfc8f240;hb=6474449850aeace128aebe2d7f387ac7c550bcc5;hp=53efa92caf1f8eb356e4c80482e908a691aa8b77;hpb=e49e47171803d37105dcb71fa92f46b3984c0feb;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 53efa92c..b989c88d 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -38,20 +38,21 @@ char *filename; int lineno; int block; int scopeLevel; +int seqPoint; symbol *returnLabel; /* function return label */ symbol *entryLabel; /* function entry label */ /*-----------------------------------------------------------------*/ /* forward definition of some functions */ -operand *geniCodeDivision (operand *, operand *); -operand *geniCodeAssign (operand *, operand *, int); -operand *geniCodeArray (operand *, operand *,int); -operand *geniCodeArray2Ptr (operand *); +operand *geniCodeAssign (operand *, operand *, int, int); +static operand *geniCodeArray (operand *, operand *,int); +static operand *geniCodeArray2Ptr (operand *); operand *geniCodeRValue (operand *, bool); operand *geniCodeDerefPtr (operand *,int); int isLvaluereq(int lvl); void setOClass (sym_link * ptr, sym_link * spec); +static operand *geniCodeCast (sym_link *, operand *, bool); #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s) /* forward definition of ic print functions */ @@ -119,7 +120,8 @@ iCodeTable codeTable[] = {ARRAYINIT, "arrayInit", picGenericOne, NULL}, {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}, {CRITICAL, "critical_start", picCritical, NULL}, - {ENDCRITICAL, "critical_end", picEndCritical, NULL} + {ENDCRITICAL, "critical_end", picEndCritical, NULL}, + {SWAP, "swap", picGenericOne, NULL} }; /*-----------------------------------------------------------------*/ @@ -143,14 +145,14 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, max = pow ((double)2.0, (double)bitsForType(ltype)); - if (SPEC_LONG(val->type)) { - if (SPEC_USIGN(val->type)) { + if (IS_LONG(val->type)) { + if (IS_UNSIGNED(val->type)) { v=SPEC_CVAL(val->type).v_ulong; } else { v=SPEC_CVAL(val->type).v_long; } } else { - if (SPEC_USIGN(val->type)) { + if (IS_UNSIGNED(val->type)) { v=SPEC_CVAL(val->type).v_uint; } else { v=SPEC_CVAL(val->type).v_int; @@ -164,21 +166,21 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, pedantic=2; #endif - if (SPEC_NOUN(ltype)==FLOAT) { + if (IS_FLOAT(ltype)) { // anything will do return; } - if (!SPEC_USIGN(val->type) && v<0) { + if (!IS_UNSIGNED(val->type) && v<0) { negative=1; - if (SPEC_USIGN(ltype) && (pedantic>1)) { + if (IS_UNSIGNED(ltype) && (pedantic>1)) { warnings++; } v=-v; } // if very pedantic: "char c=200" is not allowed - if (pedantic>1 && !SPEC_USIGN(ltype)) { + if (pedantic>1 && !IS_UNSIGNED(ltype)) { max = max/2 + negative; } @@ -189,7 +191,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, #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", + IS_UNSIGNED(ltype) ? "unsigned" : "signed", nounName(ltype), msg); werror (W_CONST_RANGE, message); @@ -221,7 +223,7 @@ printOperand (operand * op, FILE * file) case VALUE: opetype = getSpec (operandType (op)); - if (SPEC_NOUN (opetype) == V_FLOAT) + if (IS_FLOAT (opetype)) fprintf (file, "%g {", SPEC_CVAL (opetype).v_float); else fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand)); @@ -231,13 +233,13 @@ 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 ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */ +#if REGA + fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */ (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name), op->key, OP_LIVEFROM (op), OP_LIVETO (op), OP_SYMBOL (op)->stack, - op->isaddr, OP_SYMBOL (op)->isreqv, + op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc, OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr ); @@ -275,18 +277,51 @@ printOperand (operand * op, FILE * file) } } #else - fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ? - OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name)); + + fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name)); + +#if 0 + + fprintf (file, "[lr%d:%d so:%d]", + OP_LIVEFROM (op), OP_LIVETO (op), + OP_SYMBOL (op)->stack + ); +#endif + +#if 1 + { + fprintf (file, "{"); + printTypeChain (operandType (op), file); + if (SPIL_LOC (op) && IS_ITEMP (op)) + fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname); + fprintf (file, "}"); + + } +#endif + /* if assigned to registers */ - if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt) + if (OP_SYMBOL (op)->nRegs) { - 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, "]"); + if (OP_SYMBOL (op)->isspilt) + { + if (!OP_SYMBOL (op)->remat) + if (OP_SYMBOL (op)->usl.spillLoc) + fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ? + OP_SYMBOL (op)->usl.spillLoc->rname : + OP_SYMBOL (op)->usl.spillLoc->name)); + else + fprintf (file, "[err]"); + else + fprintf (file, "[remat]"); + } + else + { + int i; + fprintf (file, "["); + for (i = 0; i < OP_SYMBOL (op)->nRegs; i++) + fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i])); + fprintf (file, "]"); + } } #endif break; @@ -397,6 +432,9 @@ PRINTFUNC (picGenericOne) if (ic->op == SEND || ic->op == RECEIVE) { fprintf(of,"{argreg = %d}",ic->argreg); } + if (ic->op == IPUSH) { + fprintf(of,"{parmPush = %d}",ic->parmPush); + } fprintf (of, "\n"); } @@ -512,7 +550,7 @@ piCode (void *item, FILE * of) of = stdout; icTab = getTableEntry (ic->op); - fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t", + fprintf (of, "%s(%d:%d:%d:%d:%d)\t", ic->filename, ic->lineno, ic->seq, ic->key, ic->depth, ic->supportRtn); icTab->iCodePrint (of, ic, icTab->printName); @@ -572,6 +610,7 @@ newiCode (int op, operand * left, operand * right) ic = Safe_alloc ( sizeof (iCode)); + ic->seqPoint = seqPoint; ic->lineno = lineno; ic->filename = filename; ic->block = block; @@ -654,13 +693,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 { @@ -1036,6 +1075,40 @@ isOclsExpensive (struct memmap *oclass) 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 */ /*-----------------------------------------------------------------*/ @@ -1063,7 +1136,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms) ic = ic->next; (*pcount)++; } - + ic->generated = 1; /* make sure this is a builtin function call */ assert(IS_SYMOP(IC_LEFT(ic))); @@ -1121,14 +1194,14 @@ operandOperation (operand * left, operand * right, !IS_SPEC (type)) { /* long is handled here, because it can overflow with double */ - if (SPEC_LONG (type) || + if (IS_LONG (type) || !IS_SPEC (type)) /* signed and unsigned mul are the same, as long as the precision of the result isn't bigger than the precision of the operands. */ retval = operandFromValue (valCastLiteral (type, (TYPE_UDWORD) operandLitValue (left) * (TYPE_UDWORD) operandLitValue (right))); - else if (SPEC_USIGN (type)) /* unsigned int */ + else if (IS_UNSIGNED (type)) /* unsigned int */ { /* unsigned int is handled here in order to detect overflow */ TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) * @@ -1163,23 +1236,35 @@ operandOperation (operand * left, operand * right, } else - retval = operandFromValue (valCastLiteral (type, - operandLitValue (left) / - operandLitValue (right))); + { + if (IS_UNSIGNED (type)) + { + SPEC_USIGN (let) = 1; + SPEC_USIGN (ret) = 1; + retval = operandFromValue (valCastLiteral (type, + (TYPE_UDWORD) operandLitValue (left) / + (TYPE_UDWORD) operandLitValue (right))); + } + else + { + retval = operandFromValue (valCastLiteral (type, + operandLitValue (left) / + operandLitValue (right))); + } + } break; case '%': - if ((TYPE_UDWORD) operandLitValue (right) == 0) { + if ((TYPE_UDWORD) operandLitValue (right) == 0) + { werror (E_DIVIDE_BY_ZERO); retval = right; - } + } else { - if (SPEC_USIGN(let) || SPEC_USIGN(ret)) - /* one of the operands is unsigned */ + if (IS_UNSIGNED (type)) 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)); } @@ -1187,13 +1272,14 @@ operandOperation (operand * left, operand * right, 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)); + retval = operandFromValue (valCastLiteral (type, + ((TYPE_UDWORD) operandLitValue (left) << + (TYPE_UDWORD) 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)) + if (IS_UNSIGNED(let)) /* unsigned: logic shift right */ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >> (TYPE_UDWORD) operandLitValue (right)); @@ -1203,22 +1289,32 @@ operandOperation (operand * left, operand * right, (TYPE_UDWORD) 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 + { + /* this op doesn't care about signedness */ + TYPE_UDWORD l, r; + + l = (TYPE_UDWORD) operandLitValue (left); + r = (TYPE_UDWORD) operandLitValue (right); + /* In order to correctly compare 'signed int' and 'unsigned int' it's + neccessary to strip them to 16 bit. + Literals are reduced to their cheapest type, therefore left and + right might have different types. It's neccessary to find a + common type: int (used for char too) or long */ + if (!IS_LONG (let) && + !IS_LONG (ret)) + { + r = (TYPE_UWORD) r; + l = (TYPE_UWORD) l; + } + retval = operandFromLit (l == r); + } break; case '<': retval = operandFromLit (operandLitValue (left) < @@ -1286,7 +1382,9 @@ operandOperation (operand * left, operand * right, break; case '~': - retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left))); + retval = operandFromValue (valCastLiteral (type, + ~((TYPE_UDWORD) + operandLitValue (left)))); break; case '!': @@ -1426,7 +1524,7 @@ operandFromOperand (operand * op) nop->isLiteral = op->isLiteral; nop->usesDefs = op->usesDefs; nop->isParm = op->isParm; - + switch (nop->type) { case SYMBOL: @@ -1500,16 +1598,15 @@ operandFromSymbol (symbol * sym) 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_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 */ - !IS_STATIC (sym->etype) && /* and not declared static */ - !sym->islbl && /* not a label */ - ok && /* farspace check */ - !IS_BITVAR (sym->etype) /* not a bit variable */ + !sym->islbl && /* not a label */ + ok && /* farspace check */ + !IS_BITVAR (sym->etype) /* not a bit variable */ ) { @@ -1517,6 +1614,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; @@ -1676,10 +1774,11 @@ setOperandType (operand * op, sym_link * type) } } + /*-----------------------------------------------------------------*/ /* Get size in byte of ptr need to access an array */ /*-----------------------------------------------------------------*/ -int +static int getArraySizePtr (operand * op) { sym_link *ltype = operandType(op); @@ -1717,7 +1816,8 @@ getArraySizePtr (operand * op) /*-----------------------------------------------------------------*/ /* perform "usual unary conversions" */ /*-----------------------------------------------------------------*/ -operand * +#if 0 +static operand * usualUnaryConversions (operand * op) { if (IS_INTEGRAL (operandType (op))) @@ -1730,22 +1830,40 @@ usualUnaryConversions (operand * op) } 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; } @@ -1810,7 +1928,7 @@ geniCodeRValue (operand * op, bool force) /*-----------------------------------------------------------------*/ /* geniCodeCast - changes the value from one type to another */ /*-----------------------------------------------------------------*/ -operand * +static operand * geniCodeCast (sym_link * type, operand * op, bool implicit) { iCode *ic; @@ -1826,20 +1944,28 @@ 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_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 @@ -1855,20 +1981,31 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) errors++; } } - } else { + } else { // shouldn't do that with float, array or structure unless to void - if (!IS_VOID(getSpec(type)) && + 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 (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) { + 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)))) { + 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++; } @@ -1894,6 +2031,14 @@ 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 assignement and may simplify an */ + /* iCode to use the original (uncasted) operand. */ + /* Unfortunately, other things break when this cast is */ + /* made explicit. Need to fix this someday. */ + /* -- EEP, 2004/01/21 */ if (getSize (type) == getSize (optype) && !IS_BITFIELD (type) && !IS_FLOAT (type) && @@ -1901,11 +2046,10 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) ((IS_SPEC (type) && IS_SPEC (optype)) || (!IS_SPEC (type) && !IS_SPEC (optype)))) { - ic = newiCode ('=', NULL, op); IC_RESULT (ic) = newiTempOperand (type, 0); SPIL_LOC (IC_RESULT (ic)) = - (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL); + (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL); IC_RESULT (ic)->isaddr = 0; } else @@ -1919,10 +2063,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); } @@ -1930,7 +2076,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /*-----------------------------------------------------------------*/ /* geniCodeLabel - will create a Label */ /*-----------------------------------------------------------------*/ -void +void geniCodeLabel (symbol * label) { iCode *ic; @@ -1942,7 +2088,7 @@ geniCodeLabel (symbol * label) /*-----------------------------------------------------------------*/ /* geniCodeGoto - will create a Goto */ /*-----------------------------------------------------------------*/ -void +void geniCodeGoto (symbol * label) { iCode *ic; @@ -1954,8 +2100,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; @@ -1968,31 +2114,29 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) right->operand.valOperand)); if (IS_LITERAL(retype)) { - p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand)); + p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand)); } - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, resultType, '*'); #if 1 rtype = operandType (right); retype = getSpec (rtype); ltype = operandType (left); letype = getSpec (ltype); #endif - if (resultIsInt) - { - SPEC_NOUN(getSpec(resType))=V_INT; - } /* if the right is a literal & power of 2 */ /* then make it a left shift */ /* code generated for 1 byte * 1 byte literal = 2 bytes result is more efficient in most cases than 2 bytes result = 2 bytes << literal if port has 1 byte muldiv */ - if (p2 && !IS_FLOAT (letype) && - !((resultIsInt) && (getSize (resType) != getSize (ltype)) && - (port->support.muldiv == 1))) + if (p2 && !IS_FLOAT (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 ((resultIsInt) && (getSize (resType) != getSize (ltype))) + if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))) { /* LEFT_OP need same size for left and result, */ left = geniCodeCast (resType, left, TRUE); @@ -2017,8 +2161,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; @@ -2028,15 +2172,15 @@ 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) + IS_UNSIGNED(letype) && + (p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand)))) { ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */ } @@ -2055,8 +2199,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; @@ -2067,7 +2211,7 @@ geniCodeModulus (operand * left, operand * right) return operandFromValue (valMod (left->operand.valOperand, right->operand.valOperand)); - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, resultType, '%'); /* now they are the same size */ ic = newiCode ('%', left, right); @@ -2111,14 +2255,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; @@ -2141,12 +2286,15 @@ geniCodeSubtract (operand * left, operand * right) { 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); + resType = usualBinaryConversions (&left, &right, resultType, '-'); } ic = newiCode ('-', left, right); @@ -2165,22 +2313,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 */ @@ -2188,22 +2337,34 @@ 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, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR); + /* Even if right is a 'unsigned char', + the result will be a 'signed int' due to the promotion rules. + It doesn't make sense when accessing arrays, so let's fix it here: */ + if (indexUnsigned) + SPEC_USIGN (getSpec (operandType (right))) = 1; + } resType = copyLinkChain (ltype); } else { // make them the same size - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, resultType, '+'); } /* if they are both literals then we know */ if (IS_LITERAL (letype) && IS_LITERAL (retype) && left->isLiteral && right->isLiteral) - return operandFromValue (valPlus (valFromType (letype), - valFromType (retype))); + return operandFromValue (valPlus (valFromType (ltype), + valFromType (rtype))); ic = newiCode ('+', left, right); @@ -2222,7 +2383,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) @@ -2243,10 +2404,23 @@ aggrToPtr (sym_link * type, bool force) return ptype; } +/*------------------------------------------------------------------*/ +/* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */ +/*------------------------------------------------------------------*/ +int +aggrToPtrDclType (sym_link * type, bool force) +{ + if (IS_PTR (type) && !force) + return DCL_TYPE (type); + + /* return the pointer depending on the storage class */ + return PTR_TYPE (SPEC_OCLS (getSpec (type))); +} + /*-----------------------------------------------------------------*/ /* geniCodeArray2Ptr - array to pointer */ /*-----------------------------------------------------------------*/ -operand * +static operand * geniCodeArray2Ptr (operand * op) { sym_link *optype = operandType (op); @@ -2263,34 +2437,53 @@ 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; + 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, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR, + lvl), + lvl); + } + size = operandFromLit (getSize (ltype->next)); + SPEC_USIGN (getSpec (operandType (size))) = 1; + indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); right = geniCodeMultiply (right, - operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE)); - + size, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR); + /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules. + It doesn't make sense when accessing arrays, so let's fix it here: */ + if (indexUnsigned) + SPEC_USIGN (getSpec (operandType (right))) = 1; /* we can check for limits here */ + /* already done in SDCCast.c if (isOperandLiteral (right) && IS_ARRAY (ltype) && DCL_ELEM (ltype) && (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype)) { - werror (E_ARRAY_BOUND); - right = operandFromLit (0); + werror (W_IDX_OUT_OF_BOUNDS, + (int) operandLitValue (right) / getSize (ltype->next), + DCL_ELEM (ltype)); } + */ ic = newiCode ('+', left, right); @@ -2299,14 +2492,18 @@ geniCodeArray (operand * left, operand * right,int lvl) !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) @@ -2319,7 +2516,7 @@ geniCodeStruct (operand * left, operand * right, bool islval) right->operand.symOperand); wassert(IS_SYMOP(right)); - + /* add the offset */ ic = newiCode ('+', left, operandFromLit (element->offset)); @@ -2332,10 +2529,10 @@ geniCodeStruct (operand * left, operand * right, bool islval) 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); @@ -2371,9 +2568,11 @@ 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 @@ -2382,7 +2581,7 @@ geniCodePostInc (operand * op) IC_RESULT (ic) = result = newiTempOperand (rvtype, 0); ADDTOCHAIN (ic); - geniCodeAssign (op, result, 0); + geniCodeAssign (op, result, 0, 0); return rOp; @@ -2409,8 +2608,9 @@ geniCodePreInc (operand * op, bool lvalue) 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 @@ -2418,8 +2618,8 @@ geniCodePreInc (operand * op, bool lvalue) IC_RESULT (ic) = result = newiTempOperand (roptype, 0); ADDTOCHAIN (ic); - (void) geniCodeAssign (op, result, 0); - if (lvalue || IS_TRUE_SYMOP (op)) + (void) geniCodeAssign (op, result, 0, 0); + if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype)) return op; else return result; @@ -2454,9 +2654,11 @@ 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 @@ -2465,7 +2667,7 @@ geniCodePostDec (operand * op) IC_RESULT (ic) = result = newiTempOperand (rvtype, 0); ADDTOCHAIN (ic); - geniCodeAssign (op, result, 0); + geniCodeAssign (op, result, 0, 0); return rOp; @@ -2492,8 +2694,9 @@ geniCodePreDec (operand * op, bool lvalue) 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 @@ -2501,8 +2704,8 @@ geniCodePreDec (operand * op, bool lvalue) IC_RESULT (ic) = result = newiTempOperand (roptype, 0); ADDTOCHAIN (ic); - (void) geniCodeAssign (op, result, 0); - if (lvalue || IS_TRUE_SYMOP (op)) + (void) geniCodeAssign (op, result, 0, 0); + if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype)) return op; else return result; @@ -2691,12 +2894,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); } @@ -2718,7 +2924,7 @@ geniCodeRightShift (operand * left, operand * right) /*-----------------------------------------------------------------*/ /* geniCodeLogic- logic code */ /*-----------------------------------------------------------------*/ -operand * +static operand * geniCodeLogic (operand * left, operand * right, int op) { iCode *ic; @@ -2777,7 +2983,7 @@ geniCodeLogic (operand * left, operand * right, int op) } } - ctype = usualBinaryConversions (&left, &right); + ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0); ic = newiCode (op, left, right); IC_RESULT (ic) = newiTempOperand (newCharLink (), 1); @@ -2790,12 +2996,77 @@ geniCodeLogic (operand * left, operand * right, int op) op != NE_OP && op != AND_OP && op != OR_OP) - ic->supportRtn = 1; + ic->supportRtn = 1; ADDTOCHAIN (ic); return IC_RESULT (ic); } +/*-----------------------------------------------------------------*/ +/* geniCodeLogicAndOr - && || operations */ +/*-----------------------------------------------------------------*/ +static operand * +geniCodeLogicAndOr (ast *tree, int lvl) +{ + iCode *ic; + 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 */ + result = newiTempOperand (newCharLink(), 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 a generic unary operation */ /*-----------------------------------------------------------------*/ @@ -2829,7 +3100,7 @@ geniCodeConditional (ast * tree,int lvl) /* move the value to a new Operand */ result = newiTempOperand (tree->right->ftype, 0); - geniCodeAssign (result, geniCodeRValue (true, FALSE), 0); + geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0); /* generate an unconditional goto */ geniCodeGoto (exitLabel); @@ -2838,7 +3109,7 @@ geniCodeConditional (ast * tree,int lvl) geniCodeLabel (falseLabel); false = ast2iCode (tree->right->right,lvl+1); - geniCodeAssign (result, geniCodeRValue (false, FALSE), 0); + geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0); /* create the exit label */ geniCodeLabel (exitLabel); @@ -2850,13 +3121,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; @@ -2975,7 +3246,7 @@ geniCodeSEParms (ast * parms,int lvl) /*-----------------------------------------------------------------*/ value * geniCodeParms (ast * parms, value *argVals, int *stack, - sym_link * fetype, symbol * func,int lvl) + sym_link * ftype, int lvl) { iCode *ic; operand *pval; @@ -2985,14 +3256,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; } @@ -3005,47 +3276,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))) - { + 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); - } + /* 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; @@ -3061,6 +3332,7 @@ 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) && @@ -3074,8 +3346,12 @@ geniCodeCall (operand * left, ast * parms,int lvl) of overlaying function parameters */ geniCodeSEParms (parms,lvl); + ftype = operandType (left); + if (IS_CODEPTR (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)) { @@ -3084,7 +3360,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); @@ -3103,6 +3379,8 @@ geniCodeCall (operand * left, ast * parms,int lvl) static void geniCodeReceive (value * args) { + unsigned char paramByteCounter = 0; + /* for all arguments that are passed in registers */ while (args) { @@ -3143,6 +3421,17 @@ geniCodeReceive (value * args) first = 0; } 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); } @@ -3179,6 +3468,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* create a proc icode */ ic = newiCode (FUNCTION, func, NULL); lineno=ic->lineno = OP_SYMBOL (func)->lineDef; + ic->tree = tree; ADDTOCHAIN (ic); @@ -3194,6 +3484,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* now generate the end proc */ ic = newiCode (ENDFUNCTION, func, NULL); + ic->tree = tree; ADDTOCHAIN (ic); return; } @@ -3279,7 +3570,8 @@ exit: 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; @@ -3287,6 +3579,10 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) 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; @@ -3294,50 +3590,132 @@ 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) floatFromVal (vch = caseVals); - while (vch) + while (vch->next) { - if (((t = (int) floatFromVal (vch)) - max) != 1) - return 0; - SNPRINTF (buffer, sizeof(buffer), - "_case_%d_%d", - tree->values.switchVals.swNum, - t); - addSet (&labels, newiTempLabel (buffer)); - max = t; cnt++; vch = vch->next; } + max = (int) floatFromVal (vch); - /* 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 ((needRangeCheck && 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; - if (tree->values.switchVals.swDefault) + switch (getSize (operandType (cond))) { - SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum); + case 1: sizeIndex = 0; break; + case 2: sizeIndex = 1; break; + case 4: sizeIndex = 2; break; + default: return 0; } - else + + /* Compute the size cost of the range check and subtraction. */ + sizeofMinCost = 0; + sizeofZeroMinCost = 0; + sizeofMaxCost = 0; + if (needRangeCheck) { - SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum); + 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); + } + else + { + SNPRINTF (buffer, sizeof(buffer), + "_swBrk_%d", + tree->values.switchVals.swNum); + } falseLabel = newiTempLabel (buffer); - /* so we can create a jumptable */ + /* Build the list of labels for the jump table. */ + vch = caseVals; + t = (int) floatFromVal (vch); + for (i=min; i<=max; i++) + { + if (vch && t==i) + { + /* Explicit case: make a new label for it. */ + SNPRINTF (buffer, sizeof(buffer), + "_case_%d_%d", + tree->values.switchVals.swNum, + i); + addSet (&labels, newiTempLabel (buffer)); + vch = vch->next; + if (vch) + t = (int) floatFromVal (vch); + } + else + { + /* Implicit case: use the default label. */ + addSet (&labels, falseLabel); + } + } + + /* If cond is volatile, it might change after the boundary */ + /* conditions are tested to an out of bounds value, causing */ + /* a jump to a location outside of the jump table. To avoid */ + /* this possibility, use a non-volatile copy of it 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; + } + /* first we rule out the boundary conditions */ /* if only optimization says so */ if (needRangeCheck) @@ -3345,7 +3723,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) 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))) + if (!(min == 0 && IS_UNSIGNED (cetype))) { boundary = geniCodeLogic (cond, operandFromLit (min), '<'); ic = newiCodeCondition (boundary, falseLabel, NULL); @@ -3361,7 +3739,7 @@ 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)); + cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR); if (!IS_LITERAL(getSpec(operandType(cond)))) setOperandType (cond, UCHARTYPE); } @@ -3465,7 +3843,7 @@ geniCodeInline (ast * tree) /*-----------------------------------------------------------------*/ /* geniCodeArrayInit - intermediate code for array initializer */ /*-----------------------------------------------------------------*/ -static void +static void geniCodeArrayInit (ast * tree, operand *array) { iCode *ic; @@ -3491,11 +3869,23 @@ geniCodeCritical (ast *tree, int lvl) { iCode *ic; operand *op = NULL; + sym_link *type; + + if (!options.stackAuto) + { + type = newLink(SPECIFIER); + SPEC_VOLATILE(type) = 1; + SPEC_NOUN(type) = V_BIT; + SPEC_SCLS(type) = S_BIT; + SPEC_BLEN(type) = 1; + SPEC_BSTR(type) = 0; + op = newiTempOperand(type, 1); + } /* If op is NULL, the original interrupt state will saved on */ /* the stack. Otherwise, it will be saved in op. */ - /* Generate a save of the current interrupt state & disabled */ + /* Generate a save of the current interrupt state & disable */ ic = newiCode (CRITICAL, NULL, NULL); IC_RESULT (ic) = op; ADDTOCHAIN (ic); @@ -3593,6 +3983,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); @@ -3621,6 +4013,8 @@ 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 && @@ -3726,44 +4120,51 @@ ast2iCode (ast * tree,int lvl) 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)); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)); else return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl); case '-': - if (right) + if (right) return geniCodeSubtract (geniCodeRValue (left, FALSE), - geniCodeRValue (right, FALSE)); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)); else return geniCodeUnaryMinus (geniCodeRValue (left, FALSE)); case '+': if (right) return geniCodeAdd (geniCodeRValue (left, FALSE), - geniCodeRValue (right, FALSE),lvl); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype), + lvl); else 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: + 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 @@ -3792,28 +4193,29 @@ ast2iCode (ast * tree,int lvl) setOperandType (op, UCHARTYPE); return op; } + case AND_OP: + case OR_OP: + return geniCodeLogicAndOr (tree, lvl); case '>': case '<': case LE_OP: case GE_OP: case EQ_OP: case NE_OP: - case AND_OP: - case OR_OP: /* different compilers (even different gccs) evaluate - the two calls in a different order. to get the same - result on all machines we've to specify a clear sequence. + 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); */ { - 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); } case '?': return geniCodeConditional (tree,lvl); @@ -3831,7 +4233,7 @@ ast2iCode (ast * tree,int lvl) else right = geniCodeRValue (right, FALSE); - geniCodeAssign (left, right, 0); + geniCodeAssign (left, right, 0, 1); return right; } case MUL_ASSIGN: @@ -3839,20 +4241,26 @@ ast2iCode (ast * tree,int lvl) geniCodeAssign (left, geniCodeMultiply (geniCodeRValue (operandFromOperand (left), FALSE), - geniCodeRValue (right, FALSE),FALSE), 0); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)), + 0, 1); case DIV_ASSIGN: return geniCodeAssign (left, geniCodeDivision (geniCodeRValue (operandFromOperand (left), FALSE), - geniCodeRValue (right, FALSE)), 0); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)), + 0, 1); case MOD_ASSIGN: return geniCodeAssign (left, geniCodeModulus (geniCodeRValue (operandFromOperand (left), FALSE), - geniCodeRValue (right, FALSE)), 0); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)), + 0, 1); case ADD_ASSIGN: { sym_link *rtype = operandType (right); @@ -3867,7 +4275,10 @@ ast2iCode (ast * tree,int lvl) return geniCodeAssign (left, geniCodeAdd (geniCodeRValue (operandFromOperand (left), FALSE), - right,lvl), 0); + right, + getResultTypeFromType (tree->ftype), + lvl), + 0, 1); } case SUB_ASSIGN: { @@ -3886,20 +4297,24 @@ ast2iCode (ast * tree,int lvl) geniCodeAssign (left, geniCodeSubtract (geniCodeRValue (operandFromOperand (left), FALSE), - right), 0); + right, + getResultTypeFromType (tree->ftype)), + 0, 1); } case LEFT_ASSIGN: return geniCodeAssign (left, geniCodeLeftShift (geniCodeRValue (operandFromOperand (left) ,FALSE), - geniCodeRValue (right, FALSE)), 0); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)), + 0, 1); case RIGHT_ASSIGN: return geniCodeAssign (left, geniCodeRightShift (geniCodeRValue (operandFromOperand (left) ,FALSE), - geniCodeRValue (right, FALSE)), 0); + geniCodeRValue (right, FALSE)), 0, 1); case AND_ASSIGN: return geniCodeAssign (left, @@ -3907,7 +4322,7 @@ ast2iCode (ast * tree,int lvl) FALSE), geniCodeRValue (right, FALSE), BITWISEAND, - operandType (left)), 0); + operandType (left)), 0, 1); case XOR_ASSIGN: return geniCodeAssign (left, @@ -3915,7 +4330,7 @@ ast2iCode (ast * tree,int lvl) FALSE), geniCodeRValue (right, FALSE), '^', - operandType (left)), 0); + operandType (left)), 0, 1); case OR_ASSIGN: return geniCodeAssign (left, @@ -3923,7 +4338,7 @@ ast2iCode (ast * tree,int lvl) ,FALSE), geniCodeRValue (right, FALSE), '|', - operandType (left)), 0); + operandType (left)), 0, 1); case ',': return geniCodeRValue (right, FALSE); @@ -3963,7 +4378,7 @@ ast2iCode (ast * tree,int lvl) return NULL; case CRITICAL: - geniCodeCritical (tree, lvl); + geniCodeCritical (tree, lvl); } return NULL;