X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.c;h=9c37fe0a2d5f22cdc4197ffc06ea11eb134f0c4f;hb=017f41af54f2c9aeb55f31e237eb58762b6ea2ff;hp=7a6f05055cfd8ffe3e409fe540f7b72c765152c5;hpb=c3560462d55e84f10d737d03a1bce575bab3b8b3;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 7a6f0505..9c37fe0a 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -24,6 +24,7 @@ #include "common.h" #include "newalloc.h" +#include "math.h" /*-----------------------------------------------------------------*/ /* global variables */ @@ -40,6 +41,7 @@ int scopeLevel; symbol *returnLabel; /* function return label */ symbol *entryLabel; /* function entry label */ + /*-----------------------------------------------------------------*/ /* forward definition of some functions */ operand *geniCodeDivision (operand *, operand *); @@ -48,6 +50,7 @@ operand *geniCodeArray (operand *, operand *,int); operand *geniCodeArray2Ptr (operand *); operand *geniCodeRValue (operand *, bool); operand *geniCodeDerefPtr (operand *,int); +int isLvaluereq(int lvl); #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s) /* forward definition of ic print functions */ @@ -108,9 +111,85 @@ iCodeTable codeTable[] = {IFX, "if", picIfx, NULL}, {INLINEASM, "", picInline, NULL}, {RECEIVE, "recv", picReceive, NULL}, - {SEND, "send", picGenericOne, NULL} + {SEND, "send", picGenericOne, NULL}, + {ARRAYINIT, "arrayInit", picGenericOne, NULL}, }; +/*-----------------------------------------------------------------*/ +/* checkConstantRange: check a constant against the type */ +/*-----------------------------------------------------------------*/ + +/* pedantic=0: allmost anything is allowed as long as the absolute + value is within the bit range of the type, and -1 is treated as + 0xf..f for unsigned types (e.g. in assign) + pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare) + pedantic>1: "char c=200" is not allowed (evaluates to -56) +*/ + +void checkConstantRange(sym_link *ltype, value *val, char *msg, + int pedantic) { + double max; + int warnings=0; + int negative=0; + long v; + + max = pow ((double)2.0, (double)bitsForType(ltype)); + + if (SPEC_LONG(val->type)) { + if (SPEC_USIGN(val->type)) { + v=SPEC_CVAL(val->type).v_ulong; + } else { + v=SPEC_CVAL(val->type).v_long; + } + } else { + if (SPEC_USIGN(val->type)) { + v=SPEC_CVAL(val->type).v_uint; + } else { + v=SPEC_CVAL(val->type).v_int; + } + } + + +#if 0 + // this could be a good idea + if (options.pedantic) + pedantic=2; +#endif + + if (SPEC_NOUN(ltype)==FLOAT) { + // anything will do + return; + } + + if (!SPEC_USIGN(val->type) && v<0) { + negative=1; + if (SPEC_USIGN(ltype) && (pedantic>1)) { + warnings++; + } + v=-v; + } + + // if very pedantic: "char c=200" is not allowed + if (pedantic>1 && !SPEC_USIGN(ltype)) { + max = max/2 + negative; + } + + if (v >= max) { + warnings++; + } + +#if 0 // temporary disabled, leaving the warning as a reminder + if (warnings) { + SNPRINTF (message, sizeof(message), "for %s %s in %s", + SPEC_USIGN(ltype) ? "unsigned" : "signed", + nounName(ltype), msg); + werror (W_CONST_RANGE, message); + + if (pedantic>1) + fatalError++; + } +#endif +} /*-----------------------------------------------------------------*/ /* operandName - returns the name of the operand */ @@ -145,12 +224,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}", /*{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->isaddr, OP_SYMBOL (op)->isreqv, + OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc, + OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr ); { fprintf (file, "{"); @@ -305,6 +386,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"); } @@ -416,7 +500,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); @@ -434,7 +518,7 @@ newOperand () { operand *op; - op = Safe_calloc (1, sizeof (operand)); + op = Safe_alloc ( sizeof (operand)); op->key = 0; return op; @@ -448,7 +532,7 @@ newiCode (int op, operand * left, operand * right) { iCode *ic; - ic = Safe_calloc (1, sizeof (iCode)); + ic = Safe_alloc ( sizeof (iCode)); ic->lineno = lineno; ic->filename = filename; @@ -472,6 +556,10 @@ newiCodeCondition (operand * condition, { iCode *ic; + if (IS_VOID(operandType(condition))) { + werror(E_VOID_VALUE_USED); + } + ic = newiCode (IFX, NULL, NULL); IC_COND (ic) = condition; IC_TRUE (ic) = trueLabel; @@ -489,7 +577,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; @@ -505,11 +593,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; @@ -528,17 +621,19 @@ 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); } itmplbl->isitmp = 1; itmplbl->islbl = 1; itmplbl->key = labelKey++; - addSym (LabelTab, itmplbl, itmplbl->name, 0, 0); + addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0); return itmplbl; } @@ -550,13 +645,13 @@ newiTempPreheaderLabel () { symbol *itmplbl; - sprintf (buffer, "preHeaderLbl%d", iTempLblNum++); + SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++); itmplbl = newSymbol (buffer, 1); itmplbl->isitmp = 1; itmplbl->islbl = 1; itmplbl->key = labelKey++; - addSym (LabelTab, itmplbl, itmplbl->name, 0, 0); + addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0); return itmplbl; } @@ -602,13 +697,16 @@ 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: IC_INLINE (nic) = IC_INLINE (ic); break; + case ARRAYINIT: + IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic); + break; + default: IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic)); IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic)); @@ -701,6 +799,8 @@ isParameterToCall (value * args, operand * op) { value *tval = args; + wassert (IS_SYMOP(op)); + while (tval) { if (tval->sym && @@ -723,7 +823,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)) @@ -773,6 +873,7 @@ isOperandLiteral (operand * op) return 0; } + /*-----------------------------------------------------------------*/ /* isOperandInFarSpace - will return true if operand is in farSpace */ /*-----------------------------------------------------------------*/ @@ -801,6 +902,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 */ /*-----------------------------------------------------------------*/ @@ -816,8 +975,12 @@ 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; } /*-----------------------------------------------------------------*/ @@ -831,6 +994,31 @@ operandLitValue (operand * op) return floatFromVal (op->operand.valOperand); } +/*-----------------------------------------------------------------*/ +/* 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 - perforoms operations on operands */ /*-----------------------------------------------------------------*/ @@ -838,7 +1026,7 @@ operand * operandOperation (operand * left, operand * right, int op, sym_link * type) { - sym_link *let , *ret; + sym_link *let , *ret=NULL; operand *retval = (operand *) 0; assert (isOperandLiteral (left)); @@ -892,21 +1080,34 @@ operandOperation (operand * left, operand * right, break; case LEFT_OP: - retval = operandFromLit (((SPEC_USIGN(let) ? + retval = operandFromLit ((SPEC_USIGN(let) ? (unsigned long) operandLitValue (left) : (long) operandLitValue (left)) << (SPEC_USIGN(ret) ? (unsigned long) operandLitValue (right) : - (long) operandLitValue (right)))); + (long) 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)))); + case RIGHT_OP: { + double lval = operandLitValue(left), rval = operandLitValue(right); + double res=0; + switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0)) + { + case 0: // left=unsigned right=unsigned + res=(unsigned long)lval >> (unsigned long)rval; + break; + case 1: // left=unsigned right=signed + res=(unsigned long)lval >> (signed long)rval; + break; + case 2: // left=signed right=unsigned + res=(signed long)lval >> (unsigned long)rval; + break; + case 3: // left=signed right=signed + res=(signed long)lval >> (signed long)rval; + break; + } + retval = operandFromLit (res); break; + } case EQ_OP: retval = operandFromLit (operandLitValue (left) == operandLitValue (right)); @@ -932,16 +1133,16 @@ operandOperation (operand * left, operand * right, operandLitValue (right)); break; case BITWISEAND: - retval = operandFromLit ((unsigned long) operandLitValue (left) & - (unsigned long) operandLitValue (right)); + retval = operandFromLit ((long)operandLitValue(left) & + (long)operandLitValue(right)); break; case '|': - retval = operandFromLit ((unsigned long) operandLitValue (left) | - (unsigned long) operandLitValue (right)); + retval = operandFromLit ((long)operandLitValue (left) | + (long)operandLitValue (right)); break; case '^': - retval = operandFromLit ((unsigned long) operandLitValue (left) ^ - (unsigned long) operandLitValue (right)); + retval = operandFromLit ((long)operandLitValue (left) ^ + (long)operandLitValue (right)); break; case AND_OP: retval = operandFromLit (operandLitValue (left) && @@ -953,7 +1154,7 @@ operandOperation (operand * left, operand * right, break; case RRC: { - long i = operandLitValue (left); + long i = (long) operandLitValue (left); retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) | (i << 1)); @@ -961,7 +1162,7 @@ operandOperation (operand * left, operand * right, break; case RLC: { - long i = operandLitValue (left); + long i = (long) operandLitValue (left); retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) | (i >> 1)); @@ -1020,7 +1221,7 @@ isOperandEqual (operand * left, operand * right) return (floatFromVal (left->operand.valOperand) == floatFromVal (right->operand.valOperand)); case TYPE: - if (checkType (left->operand.typeOperand, + if (compareType (left->operand.typeOperand, right->operand.typeOperand) == 1) return 1; } @@ -1028,9 +1229,9 @@ isOperandEqual (operand * left, operand * right) return 0; } -/*-----------------------------------------------------------------*/ -/* isiCodeEqual - comapres two iCodes are returns true if yes */ -/*-----------------------------------------------------------------*/ +/*-------------------------------------------------------------------*/ +/* isiCodeEqual - compares two iCodes are equal, returns true if yes */ +/*-------------------------------------------------------------------*/ int isiCodeEqual (iCode * left, iCode * right) { @@ -1064,6 +1265,7 @@ isiCodeEqual (iCode * left, iCode * right) if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right))) return 0; } + return 1; } return 0; @@ -1088,7 +1290,6 @@ newiTempFromOp (operand * op) nop->isvolatile = op->isvolatile; nop->isGlobal = op->isGlobal; nop->isLiteral = op->isLiteral; - nop->noSpilLoc = op->noSpilLoc; nop->usesDefs = op->usesDefs; nop->isParm = op->isParm; return nop; @@ -1111,7 +1312,6 @@ operandFromOperand (operand * op) nop->isvolatile = op->isvolatile; nop->isGlobal = op->isGlobal; nop->isLiteral = op->isLiteral; - nop->noSpilLoc = op->noSpilLoc; nop->usesDefs = op->usesDefs; nop->isParm = op->isParm; @@ -1181,7 +1381,8 @@ operandFromSymbol (symbol * sym) /* under the following conditions create a register equivalent for a local symbol */ if (sym->level && sym->etype && SPEC_OCLS (sym->etype) && - (IN_FARSPACE (SPEC_OCLS (sym->etype)) && (!TARGET_IS_DS390)) && + (IN_FARSPACE (SPEC_OCLS (sym->etype)) && + (!(options.model == MODEL_FLAT24)) ) && options.stackAuto == 0) ok = 0; @@ -1190,7 +1391,7 @@ 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 */ @@ -1206,6 +1407,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; } @@ -1244,8 +1446,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); @@ -1293,7 +1493,7 @@ operandFromLink (sym_link * type) /* operandFromLit - makes an operand from a literal value */ /*-----------------------------------------------------------------*/ operand * -operandFromLit (float i) +operandFromLit (double i) { return operandFromValue (valueFromLit (i)); } @@ -1406,7 +1606,7 @@ usualUnaryConversions (operand * op) { if (IS_INTEGRAL (operandType (op))) { - if (getSize (operandType (op)) < INTSIZE) + if (getSize (operandType (op)) < (unsigned int) INTSIZE) { /* Widen to int. */ return geniCodeCast (INTTYPE, op, TRUE); @@ -1426,6 +1626,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); @@ -1466,7 +1667,8 @@ geniCodeRValue (operand * op, bool force) if (IS_SPEC (type) && IS_TRUE_SYMOP (op) && - (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390)) + (!IN_FARSPACE (SPEC_OCLS (etype)) || + (options.model == MODEL_FLAT24) )) { op = operandFromOperand (op); op->isaddr = 0; @@ -1484,10 +1686,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); @@ -1503,6 +1701,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) sym_link *optype; sym_link *opetype = getSpec (optype = operandType (op)); sym_link *restype; + int errors=0; /* one of them has size zero then error */ if (IS_VOID (optype)) @@ -1512,7 +1711,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) } /* if the operand is already the desired type then do nothing */ - if (checkType (type, optype) == 1) + if (compareType (type, optype) == 1) return op; /* if this is a literal then just change the type & return */ @@ -1520,20 +1719,63 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) return operandFromValue (valCastLiteral (type, operandLitValue (op))); - /* if casting to some pointer type && - the destination is not a generic pointer - then give a warning : (only for implicit casts) */ - if (IS_PTR (optype) && implicit && - (DCL_TYPE (optype) != DCL_TYPE (type)) && - !IS_GENPTR (type)) - { - werror (E_INCOMPAT_CAST); - werror (E_CONTINUE, "from type '"); - printTypeChain (optype, stderr); - fprintf (stderr, "' to type '"); - printTypeChain (type, stderr); - fprintf (stderr, "'\n"); + /* if casting to/from pointers, do some checking */ + if (IS_PTR(type)) { // to a pointer + if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer + if (IS_INTEGRAL(optype)) { + // maybe this is NULL, than it's ok. + if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) { + if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) { + // no way to set the storage + if (IS_LITERAL(optype)) { + werror(E_LITERAL_GENERIC); + errors++; + } else { + werror(E_NONPTR2_GENPTR); + errors++; + } + } else if (implicit) { + werror(W_INTEGRAL2PTR_NOCAST); + errors++; + } + } + } else { + // shouldn't do that with float, array or structure unless to void + if (!IS_VOID(getSpec(type)) && + !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) { + werror(E_INCOMPAT_TYPES); + errors++; + } + } + } else { // from a pointer to a pointer + if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) { + // if not a pointer to a function + if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) { + if (implicit) { // if not to generic, they have to match + if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) { + werror(E_INCOMPAT_PTYPES); + errors++; + } + } + } + } + } + } else { // to a non pointer + if (IS_PTR(optype)) { // from a pointer + if (implicit) { // sneaky + if (IS_INTEGRAL(type)) { + werror(W_PTR2INTEGRAL_NOCAST); + errors++; + } else { // shouldn't do that with float, array or structure + werror(E_INCOMPAT_TYPES); + errors++; + } + } } + } + if (errors) { + printFromToType (optype, type); + } /* if they are the same size create an assignment */ if (getSize (type) == getSize (optype) && @@ -1561,7 +1803,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); @@ -1622,7 +1865,6 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) if (resultIsInt) { SPEC_NOUN(getSpec(resType))=V_INT; - SPEC_SHORT(getSpec(resType))=0; } /* if the right is a literal & power of 2 */ @@ -1632,7 +1874,7 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) if port has 1 byte muldiv */ if (p2 && !IS_FLOAT (letype) && !((resultIsInt) && (getSize (resType) != getSize (ltype)) && - (port->muldiv.native_below == 1))) + (port->support.muldiv == 1))) { if ((resultIsInt) && (getSize (resType) != getSize (ltype))) { @@ -1672,13 +1914,16 @@ 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 */ + floatFromVal (right->operand.valOperand)))) { + ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */ + } else { ic = newiCode ('/', left, right); /* normal division */ @@ -1744,6 +1989,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))); } @@ -1800,7 +2050,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; @@ -1808,9 +2058,11 @@ geniCodeAdd (operand * left, operand * right,int lvl) int isarray = 0; LRTYPE; +#if 0 /* if left is an array then array access */ if (IS_ARRAY (ltype)) return geniCodeArray (left, right,lvl); +#endif /* if the right side is LITERAL zero */ /* return the left side */ @@ -1821,8 +2073,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 @@ -1833,7 +2085,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); } @@ -1933,7 +2185,7 @@ geniCodeArray (operand * left, operand * right,int lvl) { left = geniCodeRValue (left, FALSE); } - return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl); + return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl); } right = geniCodeMultiply (right, @@ -1974,6 +2226,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)); @@ -2020,10 +2274,10 @@ geniCodePostInc (operand * op) } rOp = newiTempOperand (rvtype, 0); - rOp->noSpilLoc = 1; + OP_SYMBOL(rOp)->noSpilLoc = 1; if (IS_ITEMP (rv)) - rv->noSpilLoc = 1; + OP_SYMBOL(rv)->noSpilLoc = 1; geniCodeAssign (rOp, rv, 0); @@ -2095,15 +2349,15 @@ geniCodePostDec (operand * op) /* if this is not an address we have trouble */ if (!op->isaddr) { - werror (E_LVALUE_REQUIRED, "++"); + werror (E_LVALUE_REQUIRED, "--"); return op; } rOp = newiTempOperand (rvtype, 0); - rOp->noSpilLoc = 1; + OP_SYMBOL(rOp)->noSpilLoc = 1; if (IS_ITEMP (rv)) - rv->noSpilLoc = 1; + OP_SYMBOL(rv)->noSpilLoc = 1; geniCodeAssign (rOp, rv, 0); @@ -2139,7 +2393,7 @@ geniCodePreDec (operand * op) if (!op->isaddr) { - werror (E_LVALUE_REQUIRED, "++"); + werror (E_LVALUE_REQUIRED, "--"); return op; } @@ -2369,12 +2623,6 @@ geniCodeRightShift (operand * left, operand * right) return IC_RESULT (ic); } -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define LONG_LONG __int64 -#else -#define LONG_LONG long long -#endif - /*-----------------------------------------------------------------*/ /* geniCodeLogic- logic code */ /*-----------------------------------------------------------------*/ @@ -2388,13 +2636,10 @@ geniCodeLogic (operand * left, operand * right, int op) /* left is integral type and right is literal then check if the literal value is within bounds */ - if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype)) + if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype)) { - int nbits = bitsForType (ltype); - long v = operandLitValue (right); - - if (v > ((LONG_LONG) 1 << nbits) && v > 0) - werror (W_CONST_RANGE, " compare operation "); + checkConstantRange(ltype, + OP_VALUE(right), "compare operation", 1); } ctype = usualBinaryConversions (&left, &right); @@ -2448,7 +2693,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 */ @@ -2486,11 +2731,8 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) check if the literal value is within bounds */ if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype)) { - int nbits = bitsForType (ltype); - long v = operandLitValue (right); - - if (v > ((LONG_LONG) 1 << nbits) && v > 0) - werror (W_CONST_RANGE, " = operation"); + checkConstantRange(ltype, + OP_VALUE(right), "= operation", 0); } /* if the left & right type don't exactly match */ @@ -2500,12 +2742,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate) /* first check the type for pointer assignement */ if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) && - checkType (ltype, rtype) < 0) + compareType (ltype, rtype) <= 0) { - if (checkType (ltype->next, rtype) < 0) + if (compareType (ltype->next, rtype) < 0) right = geniCodeCast (ltype->next, right, TRUE); } - else if (checkType (ltype, rtype) < 0) + else if (compareType (ltype, rtype) < 0) right = geniCodeCast (ltype, right, TRUE); /* if left is a true symbol & ! volatile @@ -2566,30 +2808,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 */ @@ -2612,20 +2862,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 @@ -2640,6 +2894,8 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl } } + argVals=argVals->next; + return argVals; } /*-----------------------------------------------------------------*/ @@ -2653,21 +2909,27 @@ geniCodeCall (operand * left, ast * parms,int lvl) sym_link *type, *etype; int stack = 0; + if (!IS_FUNC(OP_SYMBOL(left)->type) && + !IS_CODEPTR(OP_SYMBOL(left)->type)) { + werror (E_FUNCTION_EXPECTED); + return NULL; + } + /* take care of parameters with side-effecting function calls in them, this is required to take care of overlaying function parameters */ 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; @@ -2690,7 +2952,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); @@ -2705,7 +2967,7 @@ geniCodeReceive (value * args) if (IN_FARSPACE (SPEC_OCLS (sym->etype)) && options.stackAuto == 0 && - !TARGET_IS_DS390) + (!(options.model == MODEL_FLAT24)) ) { } else @@ -2720,8 +2982,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); } @@ -2758,10 +3024,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); @@ -2822,14 +3085,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; } @@ -2876,7 +3139,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)); @@ -2889,7 +3153,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)); @@ -2905,9 +3170,14 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) 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); @@ -2970,7 +3240,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); @@ -2984,9 +3254,13 @@ geniCodeSwitch (ast * tree,int lvl) /* 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); @@ -3008,6 +3282,27 @@ geniCodeInline (ast * tree) ADDTOCHAIN (ic); } +/*-----------------------------------------------------------------*/ +/* geniCodeArrayInit - intermediate code for array initializer */ +/*-----------------------------------------------------------------*/ +static void +geniCodeArrayInit (ast * tree, operand *array) +{ + iCode *ic; + + if (!getenv("TRY_THE_NEW_INITIALIZER")) { + ic = newiCode (ARRAYINIT, array, NULL); + IC_ARRAYILIST (ic) = tree->values.constlist; + } else { + operand *left=newOperand(), *right=newOperand(); + left->type=right->type=SYMBOL; + OP_SYMBOL(left)=AST_SYMBOL(tree->left); + OP_SYMBOL(right)=AST_SYMBOL(tree->right); + ic = newiCode (ARRAYINIT, left, right); + } + ADDTOCHAIN (ic); +} + /*-----------------------------------------------------------------*/ /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */ /* particular case. Ie : assigning or dereferencing array or ptr */ @@ -3025,7 +3320,7 @@ lvalItem; /*-----------------------------------------------------------------*/ void addLvaluereq(int lvl) { - lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem)); + lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem)); lpItem->req=1; lpItem->lvl=lvl; addSetHead(&lvaluereqSet,lpItem); @@ -3038,7 +3333,7 @@ void delLvaluereq() { lvalItem * lpItem; lpItem = getSet(&lvaluereqSet); - if(lpItem) free(lpItem); + if(lpItem) Safe_free(lpItem); } /*-----------------------------------------------------------------*/ /* clearLvaluereq - clear lvalreq flag */ @@ -3080,6 +3375,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; @@ -3157,8 +3453,9 @@ ast2iCode (ast * tree,int lvl) case '[': /* array operation */ { - sym_link *ltype = operandType (left); - left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE); + //sym_link *ltype = operandType (left); + //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE); + left = geniCodeRValue (left, FALSE); right = geniCodeRValue (right, TRUE); } @@ -3285,7 +3582,7 @@ ast2iCode (ast * tree,int lvl) sym_link *rtype = operandType (right); sym_link *ltype = operandType (left); if (IS_PTR (rtype) && IS_ITEMP (right) - && right->isaddr && checkType (rtype->next, ltype) == 1) + && right->isaddr && compareType (rtype->next, ltype) == 1) right = geniCodeRValue (right, TRUE); else right = geniCodeRValue (right, FALSE); @@ -3317,7 +3614,7 @@ ast2iCode (ast * tree,int lvl) sym_link *rtype = operandType (right); sym_link *ltype = operandType (left); if (IS_PTR (rtype) && IS_ITEMP (right) - && right->isaddr && checkType (rtype->next, ltype) == 1) + && right->isaddr && compareType (rtype->next, ltype) == 1) right = geniCodeRValue (right, TRUE); else right = geniCodeRValue (right, FALSE); @@ -3333,7 +3630,7 @@ ast2iCode (ast * tree,int lvl) sym_link *rtype = operandType (right); sym_link *ltype = operandType (left); if (IS_PTR (rtype) && IS_ITEMP (right) - && right->isaddr && checkType (rtype->next, ltype) == 1) + && right->isaddr && compareType (rtype->next, ltype) == 1) { right = geniCodeRValue (right, TRUE); } @@ -3416,6 +3713,10 @@ ast2iCode (ast * tree,int lvl) case INLINEASM: geniCodeInline (tree); return NULL; + + case ARRAYINIT: + geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1)); + return NULL; } return NULL; @@ -3453,3 +3754,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. +}