X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.c;h=a3f26e677ac067660253f6058407c220b533bab9;hb=291fc11550e1c00e40aa0c7e0403a6db200cb9ac;hp=0833e41d0cd883098ed691c04586695ed319ecf9;hpb=f754f67b0e6bdbc252b7a88ba83f919a8f48c966;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 0833e41d..a3f26e67 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -38,6 +38,7 @@ char *filename; int lineno; int block; int scopeLevel; +int seqPoint; symbol *returnLabel; /* function return label */ symbol *entryLabel; /* function entry label */ @@ -52,6 +53,7 @@ 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 */ @@ -69,6 +71,8 @@ PRINTFUNC (picJumpTable); PRINTFUNC (picInline); PRINTFUNC (picReceive); PRINTFUNC (picDummyRead); +PRINTFUNC (picCritical); +PRINTFUNC (picEndCritical); iCodeTable codeTable[] = { @@ -115,7 +119,9 @@ iCodeTable codeTable[] = {RECEIVE, "recv", picReceive, NULL}, {SEND, "send", picGenericOne, NULL}, {ARRAYINIT, "arrayInit", picGenericOne, NULL}, - {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL} + {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}, + {CRITICAL, "critical_start", picCritical, NULL}, + {ENDCRITICAL, "critical_end", picEndCritical, NULL} }; /*-----------------------------------------------------------------*/ @@ -139,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; @@ -160,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; } @@ -185,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); @@ -217,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)); @@ -473,6 +479,28 @@ PRINTFUNC (picDummyRead) 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 */ /*-----------------------------------------------------------------*/ @@ -546,6 +574,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; @@ -995,6 +1024,21 @@ isOperandOnStack (operand * op) return FALSE; } +/*-----------------------------------------------------------------*/ +/* isOclsExpensive - will return true if accesses to an output */ +/* storage class are expensive */ +/*-----------------------------------------------------------------*/ +bool +isOclsExpensive (struct memmap *oclass) +{ + if (port->oclsExpense) + return port->oclsExpense (oclass) > 0; + + /* In the absence of port specific guidance, assume only */ + /* farspace is expensive. */ + return IN_FARSPACE (oclass); +} + /*-----------------------------------------------------------------*/ /* operandLitValue - literal value of an operand */ /*-----------------------------------------------------------------*/ @@ -1022,7 +1066,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))); @@ -1080,22 +1124,21 @@ 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) * (TYPE_UWORD) operandLitValue (right); retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul)); - if (!options.lessPedantic && - ul != (TYPE_UWORD) ul) + if (ul != (TYPE_UWORD) ul) werror (W_INT_OVL); } else /* signed int */ @@ -1105,8 +1148,7 @@ operandOperation (operand * left, operand * right, (TYPE_WORD) operandLitValue (right); retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l)); - if (!options.lessPedantic && - l != (TYPE_WORD) l) + if (l != (TYPE_WORD) l) werror (W_INT_OVL); } } @@ -1124,23 +1166,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)); } @@ -1154,7 +1208,7 @@ operandOperation (operand * left, operand * right, 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)); @@ -1169,14 +1223,14 @@ operandOperation (operand * left, operand * right, TYPE_UDWORD l, r; l = (TYPE_UDWORD) operandLitValue (left); - if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR) + if (IS_CHAR(OP_VALUE(left)->type)) l &= 0xff; - else if (!SPEC_LONG (OP_VALUE(left)->type)) + else if (!IS_LONG (OP_VALUE(left)->type)) l &= 0xffff; r = (TYPE_UDWORD) operandLitValue (right); - if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR) + if (IS_CHAR(OP_VALUE(right)->type)) r &= 0xff; - else if (!SPEC_LONG (OP_VALUE(right)->type)) + else if (!IS_LONG (OP_VALUE(right)->type)) r &= 0xffff; retval = operandFromLit (l == r); } @@ -1387,7 +1441,7 @@ operandFromOperand (operand * op) nop->isLiteral = op->isLiteral; nop->usesDefs = op->usesDefs; nop->isParm = op->isParm; - + switch (nop->type) { case SYMBOL: @@ -1455,6 +1509,7 @@ operandFromSymbol (symbol * sym) register equivalent for a local symbol */ if (sym->level && sym->etype && SPEC_OCLS (sym->etype) && (IN_FARSPACE (SPEC_OCLS (sym->etype)) && + !TARGET_IS_HC08 && (!(options.model == MODEL_FLAT24)) ) && options.stackAuto == 0) ok = 0; @@ -1677,7 +1732,7 @@ getArraySizePtr (operand * op) /*-----------------------------------------------------------------*/ /* perform "usual unary conversions" */ /*-----------------------------------------------------------------*/ -operand * +static operand * usualUnaryConversions (operand * op) { if (IS_INTEGRAL (operandType (op))) @@ -1694,18 +1749,29 @@ usualUnaryConversions (operand * op) /*-----------------------------------------------------------------*/ /* perform "usual binary conversions" */ /*-----------------------------------------------------------------*/ -sym_link * -usualBinaryConversions (operand ** op1, operand ** op2) +static sym_link * +usualBinaryConversions (operand ** op1, operand ** op2, + bool promoteCharToInt, bool isMul) { sym_link *ctype; sym_link *rtype = operandType (*op2); sym_link *ltype = operandType (*op1); - - ctype = computeType (ltype, rtype); + + ctype = computeType (ltype, rtype, promoteCharToInt); + + /* special for multiplication: + This if for 'mul a,b', which takes two chars and returns an int */ + if ( isMul + /* && promoteCharToInt superfluous, already handled by computeType() */ + && IS_CHAR (getSpec (ltype)) + && IS_CHAR (getSpec (rtype)) + && !(IS_UNSIGNED (getSpec (rtype)) ^ IS_UNSIGNED (getSpec (ltype))) + && IS_INT (getSpec (ctype))) + return ctype; *op1 = geniCodeCast (ctype, *op1, TRUE); *op2 = geniCodeCast (ctype, *op2, TRUE); - + return ctype; } @@ -1734,7 +1800,7 @@ geniCodeRValue (operand * op, bool force) /* if this is not a temp symbol then */ if (!IS_ITEMP (op) && !force && - !IN_FARSPACE (SPEC_OCLS (etype))) + !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08)) { op = operandFromOperand (op); op->isaddr = 0; @@ -1743,7 +1809,7 @@ geniCodeRValue (operand * op, bool force) if (IS_SPEC (type) && IS_TRUE_SYMOP (op) && - (!IN_FARSPACE (SPEC_OCLS (etype)) || + (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) || (options.model == MODEL_FLAT24) )) { op = operandFromOperand (op); @@ -1770,7 +1836,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; @@ -1792,14 +1858,16 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /* 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 @@ -1815,9 +1883,9 @@ 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++; @@ -1827,7 +1895,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) 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 (implicit) { // if not to generic, they have to match if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) { werror(E_INCOMPAT_PTYPES); errors++; @@ -1861,11 +1929,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 @@ -1890,7 +1957,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) /*-----------------------------------------------------------------*/ /* geniCodeLabel - will create a Label */ /*-----------------------------------------------------------------*/ -void +void geniCodeLabel (symbol * label) { iCode *ic; @@ -1902,7 +1969,7 @@ geniCodeLabel (symbol * label) /*-----------------------------------------------------------------*/ /* geniCodeGoto - will create a Goto */ /*-----------------------------------------------------------------*/ -void +void geniCodeGoto (symbol * label) { iCode *ic; @@ -1915,7 +1982,7 @@ geniCodeGoto (symbol * label) /* geniCodeMultiply - gen intermediate code for multiplication */ /*-----------------------------------------------------------------*/ operand * -geniCodeMultiply (operand * left, operand * right,int resultIsInt) +geniCodeMultiply (operand * left, operand * right, int resultIsInt) { iCode *ic; int p2 = 0; @@ -1928,20 +1995,16 @@ 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, resultIsInt, TRUE); #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 */ @@ -1988,15 +2051,15 @@ geniCodeDivision (operand * left, operand * right) sym_link *ltype = operandType (left); sym_link *letype = getSpec (ltype); - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, TRUE, FALSE); /* 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 */ } @@ -2027,7 +2090,7 @@ geniCodeModulus (operand * left, operand * right) return operandFromValue (valMod (left->operand.valOperand, right->operand.valOperand)); - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, TRUE, FALSE); /* now they are the same size */ ic = newiCode ('%', left, right); @@ -2068,7 +2131,7 @@ 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))); @@ -2106,7 +2169,7 @@ geniCodeSubtract (operand * left, operand * right) } else { /* make them the same size */ - resType = usualBinaryConversions (&left, &right); + resType = usualBinaryConversions (&left, &right, FALSE, FALSE); } ic = newiCode ('-', left, right); @@ -2132,15 +2195,16 @@ geniCodeAdd (operand * left, operand * right, int lvl) 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 */ @@ -2148,22 +2212,29 @@ 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)); + indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); + right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE)); + /* 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, FALSE, FALSE); } /* 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); @@ -2228,6 +2299,7 @@ geniCodeArray (operand * left, operand * right,int lvl) { iCode *ic; sym_link *ltype = operandType (left); + bool indexUnsigned; if (IS_PTR (ltype)) { @@ -2235,12 +2307,16 @@ geniCodeArray (operand * left, operand * right,int lvl) { left = geniCodeRValue (left, FALSE); } + return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl); } - + indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); right = geniCodeMultiply (right, operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE)); - + /* 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 */ if (isOperandLiteral (right) && IS_ARRAY (ltype) && @@ -2260,11 +2336,12 @@ geniCodeArray (operand * left, operand * right,int lvl) IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next)); 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) @@ -2350,7 +2427,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); @@ -2376,8 +2453,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 || IS_TRUE_SYMOP (op)) + return op; + else + return result; } /*-----------------------------------------------------------------*/ @@ -2430,7 +2510,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); @@ -2456,8 +2536,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 || IS_TRUE_SYMOP (op)) + return op; + else + return result; } @@ -2491,6 +2574,13 @@ geniCodeAddressOf (operand * op) sym_link *optype = operandType (op); sym_link *opetype = getSpec (optype); + if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype)) + { + op = operandFromOperand (op); + op->isaddr = 0; + return op; + } + /* lvalue check already done in decorateType */ /* this must be a lvalue */ /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */ @@ -2640,6 +2730,7 @@ geniCodeLeftShift (operand * left, operand * right) { iCode *ic; + left = usualUnaryConversions (left); ic = newiCode (LEFT_OP, left, right); IC_RESULT (ic) = newiTempOperand (operandType (left), 0); ADDTOCHAIN (ic); @@ -2722,7 +2813,7 @@ geniCodeLogic (operand * left, operand * right, int op) } } - ctype = usualBinaryConversions (&left, &right); + ctype = usualBinaryConversions (&left, &right, FALSE, FALSE); ic = newiCode (op, left, right); IC_RESULT (ic) = newiTempOperand (newCharLink (), 1); @@ -2830,11 +2921,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) else if (compareType (ltype, rtype) < 0) right = geniCodeCast (ltype, right, TRUE); - /* if left is a true symbol & ! volatile + /* If left is a true symbol & ! volatile create an assignment to temporary for the right & then assign this temporary - to the symbol this is SSA . isn't it simple - and folks have published mountains of paper on it */ + to the symbol. This is SSA (static single + assignment). Isn't it simple and folks have + published mountains of paper on it */ if (IS_TRUE_SYMOP (left) && !isOperandVolatile (left, FALSE) && isOperandGlobal (left)) @@ -2862,6 +2954,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 */ /*-----------------------------------------------------------------*/ @@ -2992,7 +3102,7 @@ geniCodeCall (operand * left, ast * parms,int lvl) if (!IS_FUNC(OP_SYMBOL(left)->type) && !IS_CODEPTR(OP_SYMBOL(left)->type)) { werror (E_FUNCTION_EXPECTED); - return NULL; + return operandFromValue(valueFromLit(0)); } /* take care of parameters with side-effecting @@ -3045,7 +3155,7 @@ geniCodeReceive (value * args) if (!sym->addrtaken && !IS_VOLATILE (sym->etype)) { - if (IN_FARSPACE (SPEC_OCLS (sym->etype)) && + if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) && options.stackAuto == 0 && (!(options.model == MODEL_FLAT24)) ) { @@ -3271,7 +3381,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); @@ -3288,7 +3398,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 */ @@ -3309,6 +3420,29 @@ geniCodeSwitch (ast * tree,int lvl) 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)) @@ -3333,7 +3467,7 @@ geniCodeSwitch (ast * tree,int lvl) } - +defaultOrBreak: /* if default is present then goto break else break */ if (tree->values.switchVals.swDefault) { @@ -3384,6 +3518,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 */ @@ -3467,6 +3629,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); @@ -3479,8 +3643,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; } @@ -3493,7 +3663,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) || @@ -3566,13 +3737,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) @@ -3606,7 +3777,7 @@ ast2iCode (ast * tree,int lvl) return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl); case '-': - if (right) + if (right) return geniCodeSubtract (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE)); else @@ -3626,11 +3797,11 @@ 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 @@ -3649,6 +3820,7 @@ ast2iCode (ast * tree,int lvl) case '~': case RRC: case RLC: + case SWAP: return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op); case '!': @@ -3827,6 +3999,9 @@ ast2iCode (ast * tree,int lvl) case ARRAYINIT: geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1)); return NULL; + + case CRITICAL: + geniCodeCritical (tree, lvl); } return NULL;