X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCast.c;h=8e20910cf1c505dae56081cc9e485c210bbe0a52;hb=67613b6eceb41c8a242c2556a0f59311adb0b388;hp=82b73603ac4bb8298e977a1f1a4d029d801a4e4c;hpb=6bbbfabeec7c1456be6cc8d4238b46f59e5d5a53;p=fw%2Fsdcc diff --git a/src/SDCCast.c b/src/SDCCast.c index 82b73603..8e20910c 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -52,6 +52,7 @@ static ast *createIval (ast *, sym_link *, initList *, ast *); static ast *createIvalCharPtr (ast *, sym_link *, ast *); static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); +ast *optimizeSWAP (ast *); ast *optimizeGetHbit (ast *); ast *backPatchLabels (ast *, symbol *, symbol *); void PA(ast *t); @@ -83,6 +84,7 @@ newAst_ (unsigned type) ex->level = NestLevel; ex->block = currBlockno; ex->initMode = inInitMode; + ex->seqPoint = seqPointNo; return ex; } @@ -159,7 +161,7 @@ newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel) /*-----------------------------------------------------------------*/ /* copyAstValues - copies value portion of ast if needed */ /*-----------------------------------------------------------------*/ -void +void copyAstValues (ast * dest, ast * src) { switch (src->opval.op) @@ -184,7 +186,7 @@ copyAstValues (ast * dest, ast * src) case ARRAYINIT: dest->values.constlist = copyLiteralList(src->values.constlist); break; - + case FOR: AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel)); AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel)); @@ -201,7 +203,7 @@ copyAstValues (ast * dest, ast * src) /* copyAst - makes a copy of a given astession */ /*-----------------------------------------------------------------*/ ast * -copyAst (ast * src) +copyAst (ast * src) { ast *dest; @@ -258,24 +260,70 @@ ast *removeIncDecOps (ast * tree) { if (!tree) return NULL; - if (tree->type == EX_OP && + if (tree->type == EX_OP && (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) { if (tree->left) tree=tree->left; - else + else tree=tree->right; } tree->left=removeIncDecOps(tree->left); tree->right=removeIncDecOps(tree->right); - + + return tree; +} + +/*-----------------------------------------------------------------*/ +/* removePreIncDecOps: remove for side effects in *_ASSIGN's */ +/* "*++s += 3" -> "*++s = *++s + 3" */ +/*-----------------------------------------------------------------*/ +ast *removePreIncDecOps (ast * tree) { + + // traverse the tree and remove pre-inc/dec ops + + if (!tree) + return NULL; + + if (tree->type == EX_OP && + (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) { + if (tree->right) + tree=tree->right; + } + + tree->left=removePreIncDecOps(tree->left); + tree->right=removePreIncDecOps(tree->right); + + return tree; +} + +/*-----------------------------------------------------------------*/ +/* removePostIncDecOps: remove for side effects in *_ASSIGN's */ +/* "*s++ += 3" -> "*s++ = *s++ + 3" */ +/*-----------------------------------------------------------------*/ +ast *removePostIncDecOps (ast * tree) { + + // traverse the tree and remove pre-inc/dec ops + + if (!tree) + return NULL; + + if (tree->type == EX_OP && + (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) { + if (tree->left) + tree=tree->left; + } + + tree->left=removePostIncDecOps(tree->left); + tree->right=removePostIncDecOps(tree->right); + return tree; } /*-----------------------------------------------------------------*/ /* hasSEFcalls - returns TRUE if tree has a function call */ /*-----------------------------------------------------------------*/ -bool +bool hasSEFcalls (ast * tree) { if (!tree) @@ -296,7 +344,7 @@ hasSEFcalls (ast * tree) /*-----------------------------------------------------------------*/ /* isAstEqual - compares two asts & returns 1 if they are equal */ /*-----------------------------------------------------------------*/ -int +static int isAstEqual (ast * t1, ast * t2) { if (!t1 && !t2) @@ -382,7 +430,8 @@ resolveSymbols (ast * tree) tree->trueLabel->name))) tree->trueLabel = csym; else - werror (E_LABEL_UNDEF, tree->trueLabel->name); + werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF, + tree->trueLabel->name); } if (tree->falseLabel) @@ -392,7 +441,8 @@ resolveSymbols (ast * tree) tree->falseLabel->name))) tree->falseLabel = csym; else - werror (E_LABEL_UNDEF, tree->falseLabel->name); + werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF, + tree->falseLabel->name); } } @@ -407,7 +457,8 @@ resolveSymbols (ast * tree) tree->opval.val->sym->name); if (!csym) - werror (E_LABEL_UNDEF, tree->opval.val->sym->name); + werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF, + tree->opval.val->sym->name); else tree->opval.val->sym = csym; @@ -446,7 +497,9 @@ resolveSymbols (ast * tree) tree->opval.val->sym->etype = newIntLink (); tree->opval.val->etype = tree->opval.val->etype; tree->opval.val->type = tree->opval.val->sym->type; - werror (W_IMPLICIT_FUNC, tree->opval.val->sym->name); + werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC, + tree->opval.val->sym->name); + //tree->opval.val->sym->undefined = 1; allocVariables (tree->opval.val->sym); } else @@ -555,7 +608,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) args = args->next = newValue (); } } - + /* save it */ addSymChain (sym); sym->cdef = 1; @@ -567,7 +620,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) /*-----------------------------------------------------------------*/ /* reverseParms - will reverse a parameter tree */ /*-----------------------------------------------------------------*/ -static void +static void reverseParms (ast * ptree) { ast *ttree; @@ -591,37 +644,48 @@ reverseParms (ast * ptree) /* processParms - makes sure the parameters are okay and do some */ /* processing with them */ /*-----------------------------------------------------------------*/ -int -processParms (ast * func, +static int +processParms (ast *func, value *defParm, - ast * actParm, - int *parmNumber, // unused, although updated + ast *actParm, + int *parmNumber, /* unused, although updated */ bool rightmost) { + RESULT_TYPE resultType; + sym_link *functype; + /* if none of them exist */ if (!defParm && !actParm) return 0; - if (defParm) { - if (getenv("DEBUG_SANITY")) { - fprintf (stderr, "processParms: %s ", defParm->name); + if (defParm) + { + if (getenv("DEBUG_SANITY")) + { + fprintf (stderr, "processParms: %s ", defParm->name); + } + /* make sure the type is complete and sane */ + checkTypeSanity(defParm->etype, defParm->name); } - /* make sure the type is complete and sane */ - checkTypeSanity(defParm->etype, defParm->name); - } + if (IS_CODEPTR (func->ftype)) + functype = func->ftype->next; + else + functype = func->ftype; + /* if the function is being called via a pointer & */ /* it has not been defined a reentrant then we cannot */ /* have parameters */ - if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto) + if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto) { werror (W_NONRENT_ARGS); + fatalError++; return 1; } /* if defined parameters ended but actual parameters */ /* exist and this is not defined as a variable arg */ - if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype)) + if (!defParm && actParm && !IFFUNC_HASVARARGS(functype)) { werror (E_TOO_MANY_PARMS); return 1; @@ -634,13 +698,43 @@ processParms (ast * func, return 1; } - if (IS_VOID(actParm->ftype)) { - werror (E_VOID_VALUE_USED); - return 1; - } + /* if this is a PARAM node then match left & right */ + if (actParm->type == EX_OP && actParm->opval.op == PARAM) + { + actParm->decorated = 1; + return (processParms (func, defParm, + actParm->left, parmNumber, FALSE) || + processParms (func, defParm ? defParm->next : NULL, + actParm->right, parmNumber, rightmost)); + } + else if (defParm) /* not vararg */ + { + /* If we have found a value node by following only right-hand links, + * then we know that there are no more values after us. + * + * Therefore, if there are more defined parameters, the caller didn't + * supply enough. + */ + if (rightmost && defParm->next) + { + werror (E_TOO_FEW_PARMS); + return 1; + } + } + + /* decorate parameter */ + resultType = defParm ? getResultTypeFromType (defParm->etype) : + RESULT_TYPE_NONE; + actParm = decorateType (actParm, resultType); + + if (IS_VOID(actParm->ftype)) + { + werror (E_VOID_VALUE_USED); + return 1; + } /* If this is a varargs function... */ - if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype)) + if (!defParm && actParm && IFFUNC_HASVARARGS(functype)) { ast *newType = NULL; sym_link *ftype; @@ -653,25 +747,12 @@ processParms (ast * func, } ftype = actParm->ftype; - - /* If it's a small integer, upcast to int. */ + + /* If it's a char, upcast to int. */ if (IS_INTEGRAL (ftype) && (getSize (ftype) < (unsigned) INTSIZE)) { - if (IS_AST_OP(actParm) && - (actParm->opval.op == LEFT_OP || - actParm->opval.op == '*' || - actParm->opval.op == '+' || - actParm->opval.op == '-') && - actParm->right) { - // we should cast an operand instead of the result - actParm->decorated = 0; - actParm->left = newNode( CAST, newAst_LINK(newIntLink()), - actParm->left); - actParm = decorateType(actParm); - } else { - newType = newAst_LINK(INTTYPE); - } + newType = newAst_LINK(INTTYPE); } if (IS_PTR(ftype) && !IS_GENPTR(ftype)) @@ -685,74 +766,53 @@ processParms (ast * func, newType = newAst_LINK (copyLinkChain (ftype)); DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; } + if (newType) { /* cast required; change this op to a cast. */ - ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm))); + ast *parmCopy = resolveSymbols (copyAst (actParm)); actParm->type = EX_OP; actParm->opval.op = CAST; actParm->left = newType; actParm->right = parmCopy; - decorateType (actParm); - } - else if (actParm->type == EX_OP && actParm->opval.op == PARAM) - { - return (processParms (func, NULL, actParm->left, parmNumber, FALSE) || - processParms (func, NULL, actParm->right, parmNumber, rightmost)); + actParm->decorated = 0; /* force typechecking */ + decorateType (actParm, RESULT_TYPE_NONE); } return 0; - } + } /* vararg */ /* if defined parameters ended but actual has not & */ /* reentrant */ if (!defParm && actParm && - (options.stackAuto || IFFUNC_ISREENT (func->ftype))) + (options.stackAuto || IFFUNC_ISREENT (functype))) return 0; resolveSymbols (actParm); - /* if this is a PARAM node then match left & right */ - if (actParm->type == EX_OP && actParm->opval.op == PARAM) - { - return (processParms (func, defParm, actParm->left, parmNumber, FALSE) || - processParms (func, defParm->next, actParm->right, parmNumber, rightmost)); - } - else + + /* the parameter type must be at least castable */ + if (compareType (defParm->type, actParm->ftype) == 0) { - /* If we have found a value node by following only right-hand links, - * then we know that there are no more values after us. - * - * Therefore, if there are more defined parameters, the caller didn't - * supply enough. - */ - if (rightmost && defParm->next) - { - werror (E_TOO_FEW_PARMS); - return 1; - } + werror (E_INCOMPAT_TYPES); + printFromToType (actParm->ftype, defParm->type); + return 1; } - /* the parameter type must be at least castable */ - if (compareType (defParm->type, actParm->ftype) == 0) { - werror (E_INCOMPAT_TYPES); - printFromToType (actParm->ftype, defParm->type); - return 1; - } - /* if the parameter is castable then add the cast */ if (compareType (defParm->type, actParm->ftype) < 0) { - ast *pTree = decorateType(resolveSymbols (copyAst (actParm))); + ast *pTree; + resultType = getResultTypeFromType (defParm->etype); + pTree = resolveSymbols (copyAst (actParm)); + /* now change the current one to a cast */ actParm->type = EX_OP; actParm->opval.op = CAST; actParm->left = newAst_LINK (defParm->type); actParm->right = pTree; - actParm->etype = defParm->etype; - actParm->ftype = defParm->type; - actParm->decorated=0; /* force typechecking */ - decorateType (actParm); + actParm->decorated = 0; /* force typechecking */ + decorateType (actParm, resultType); } /* make a copy and change the regparm type to the defined parm */ @@ -762,6 +822,7 @@ processParms (ast * func, (*parmNumber)++; return 0; } + /*-----------------------------------------------------------------*/ /* createIvalType - generates ival for basic types */ /*-----------------------------------------------------------------*/ @@ -774,8 +835,8 @@ createIvalType (ast * sym, sym_link * type, initList * ilist) if (ilist->type == INIT_DEEP) ilist = ilist->init.deep; - iExpr = decorateType (resolveSymbols (list2expr (ilist))); - return decorateType (newNode ('=', sym, iExpr)); + iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK); + return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK); } /*-----------------------------------------------------------------*/ @@ -805,13 +866,14 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) break; sflds->implicit = 1; lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds))); - lAst = decorateType (resolveSymbols (lAst)); - rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast))); + lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK); + rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK); } if (iloop) { - werror (W_EXCESS_INITIALIZERS, "struct", - sym->opval.val->sym->name, sym->opval.val->sym->lineDef); + werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef, + W_EXCESS_INITIALIZERS, "struct", + sym->opval.val->sym->name); } return rast; @@ -835,9 +897,9 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) if (IS_CHAR (type->next)) if ((rast = createIvalCharPtr (sym, type, - decorateType (resolveSymbols (list2expr (ilist)))))) + decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK)))) - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); /* not the special case */ if (ilist->type != INIT_DEEP) @@ -853,7 +915,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) { ast *aSym; - aSym = decorateType (resolveSymbols(sym)); + aSym = decorateType (resolveSymbols(sym), RESULT_CHECK); rast = newNode(ARRAYINIT, aSym, NULL); rast->values.constlist = literalL; @@ -870,8 +932,9 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) // Array size was specified, and we have more initializers than needed. char *name=sym->opval.val->sym->name; int lineno=sym->opval.val->sym->lineDef; + char *filename=sym->opval.val->sym->fileDef; - werror (W_EXCESS_INITIALIZERS, "array", name, lineno); + werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); } } else @@ -881,7 +944,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) ast *aSym; aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); - aSym = decorateType (resolveSymbols (aSym)); + aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK); rast = createIval (aSym, type->next, iloop, rast); iloop = (iloop ? iloop->next : NULL); if (!iloop) @@ -896,7 +959,8 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) // there has to be a better way char *name=sym->opval.val->sym->name; int lineno=sym->opval.val->sym->lineDef; - werror (W_EXCESS_INITIALIZERS, "array", name, lineno); + char *filename=sym->opval.val->sym->fileDef; + werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); break; } @@ -909,7 +973,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) DCL_ELEM (type) = size; } - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); } @@ -938,8 +1002,18 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /* to the array element */ char *s = SPEC_CVAL (iexpr->etype).v_char; int i = 0; + int size = getSize (iexpr->ftype); + int symsize = getSize (type); + + if (size>symsize) + { + if (size>(symsize+1)) + werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS, + "string", sym->opval.val->sym->name); + size = symsize; + } - while (*s) + for (i=0;itype == INIT_DEEP) ilist = ilist->init.deep; - iexpr = decorateType (resolveSymbols (list2expr (ilist))); + iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK); /* if character pointer */ if (IS_CHAR (type->next)) @@ -1015,11 +1082,11 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* if type is SPECIFIER */ if (IS_SPEC (type)) rast = createIvalType (sym, type, ilist); - + if (wid) - return decorateType (resolveSymbols (newNode (NULLOP, wid, rast))); + return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK); else - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); } /*-----------------------------------------------------------------*/ @@ -1046,7 +1113,7 @@ gatherAutoInit (symbol * autoChain) /* resolve the symbols in the ival */ if (sym->ival) - resolveIvalSym (sym->ival); + resolveIvalSym (sym->ival, sym->type); /* if this is a static variable & has an */ /* initial value the code needs to be lifted */ @@ -1067,8 +1134,9 @@ gatherAutoInit (symbol * autoChain) work = initAggregates (sym, sym->ival, NULL); } else { if (getNelements(sym->type, sym->ival)>1) { - werror (W_EXCESS_INITIALIZERS, "scalar", - sym->name, sym->lineDef); + werrorfl (sym->fileDef, sym->lineDef, + W_EXCESS_INITIALIZERS, "scalar", + sym->name); } work = newNode ('=', newAst_VALUE (symbolVal (newSym)), list2expr (sym->ival)); @@ -1102,8 +1170,9 @@ gatherAutoInit (symbol * autoChain) work = initAggregates (sym, sym->ival, NULL); } else { if (getNelements(sym->type, sym->ival)>1) { - werror (W_EXCESS_INITIALIZERS, "scalar", - sym->name, sym->lineDef); + werrorfl (sym->fileDef, sym->lineDef, + W_EXCESS_INITIALIZERS, "scalar", + sym->name); } work = newNode ('=', newAst_VALUE (symbolVal (sym)), list2expr (sym->ival)); @@ -1147,12 +1216,14 @@ stringToSymbol (value * val) static int charLbl = 0; symbol *sym; set *sp; + int size; // have we heard this before? for (sp=statsg->syms; sp; sp=sp->next) { sym=sp->item; - if (sym->isstrlit && - !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) { + size = getSize (sym->type); + if (sym->isstrlit && size == getSize (val->type) && + !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) { // yes, this is old news. Don't publish it again. sym->isstrlit++; // but raise the usage count return symbolVal(sym); @@ -1220,6 +1291,7 @@ processBlockVars (ast * tree, int *stack, int action) return tree; } + /*-------------------------------------------------------------*/ /* constExprTree - returns TRUE if this tree is a constant */ /* expression */ @@ -1230,8 +1302,8 @@ bool constExprTree (ast *cexpr) { return TRUE; } - cexpr = decorateType (resolveSymbols (cexpr)); - + cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK); + switch (cexpr->type) { case EX_VALUE: @@ -1251,6 +1323,7 @@ bool constExprTree (ast *cexpr) { IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) { // a symbol in code space will never change // This is only for the 'char *s="hallo"' case and will have to leave + //printf(" code space symbol"); return TRUE; } return FALSE; @@ -1293,7 +1366,7 @@ bool constExprTree (ast *cexpr) { value * constExprValue (ast * cexpr, int check) { - cexpr = decorateType (resolveSymbols (cexpr)); + cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK); /* if this is not a constant then */ if (!IS_LITERAL (cexpr->ftype)) @@ -1317,11 +1390,15 @@ constExprValue (ast * cexpr, int check) if (IS_AST_OP (cexpr) && cexpr->opval.op == CAST && IS_LITERAL (cexpr->right->ftype)) + { return valCastLiteral (cexpr->ftype, floatFromVal (cexpr->right->opval.val)); + } if (IS_AST_VALUE (cexpr)) + { return cexpr->opval.val; + } if (check) werror (E_CONST_EXPECTED, "found expression"); @@ -1525,7 +1602,7 @@ astHasSymbol (ast * tree, symbol * sym) else return FALSE; } - + return astHasSymbol (tree->left, sym) || astHasSymbol (tree->right, sym); } @@ -1590,7 +1667,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) return TRUE; /*------------------------------------------------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: case DEC_OP: /* sure we are not sym is not modified */ @@ -1658,6 +1735,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case RRC: case RLC: case GETHBIT: + case SWAP: if (IS_AST_SYM_VALUE (pbody->left) && isSymbolEqual (AST_SYMBOL (pbody->left), sym)) return FALSE; @@ -1677,6 +1755,14 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case ':': case SIZEOF: /* evaluate wihout code generation */ + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + + if (IS_AST_SYM_VALUE (pbody->right) && + isSymbolEqual (AST_SYMBOL (pbody->right), sym)) + return FALSE; + return isConformingBody (pbody->left, sym, body) && isConformingBody (pbody->right, sym, body); @@ -1697,14 +1783,14 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) return FALSE; // if the loopvar is used in another (maybe conditional) block if (astHasSymbol (pbody->right, sym) && - (pbody->level > body->level)) { + (pbody->level >= body->level)) { return FALSE; } } if (astHasVolatile (pbody->left)) return FALSE; - + if (astHasDeref(pbody->right)) return FALSE; return isConformingBody (pbody->left, sym, body) && @@ -1771,7 +1857,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /* if the for loop is reversible. If yes will set the value of */ /* the loop control var & init value & termination value */ /*-----------------------------------------------------------------*/ -bool +bool isLoopReversible (ast * loop, symbol ** loopCntrl, ast ** init, ast ** end) { @@ -1855,10 +1941,10 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) newNode ('=', newAst_VALUE (symbolVal (sym)), end)); - + replLoopSym (loop->left, sym); setAstLineno (rloop, init->lineno); - + rloop = newNode (NULLOP, newNode ('=', newAst_VALUE (symbolVal (sym)), @@ -1871,22 +1957,223 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) newAst_VALUE (symbolVal (sym)), newAst_VALUE (constVal ("1"))), rloop)))); - + rloop->lineno=init->lineno; - return decorateType (rloop); + return decorateType (rloop, RESULT_CHECK); + +} + +/*-----------------------------------------------------------------*/ +/* searchLitOp - search tree (*ops only) for an ast with literal */ +/*-----------------------------------------------------------------*/ +static ast * +searchLitOp (ast *tree, ast **parent, const char *ops) +{ + ast *ret; + + if (tree && optimize.global_cse) + { + /* is there a literal operand? */ + if (tree->right && + IS_AST_OP(tree->right) && + tree->right->right && + (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1])) + { + if (IS_LITERAL (RTYPE (tree->right)) ^ + IS_LITERAL (LTYPE (tree->right))) + { + tree->right->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->right; + } + ret = searchLitOp (tree->right, parent, ops); + if (ret) + return ret; + } + if (tree->left && + IS_AST_OP(tree->left) && + tree->left->right && + (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1])) + { + if (IS_LITERAL (RTYPE (tree->left)) ^ + IS_LITERAL (LTYPE (tree->left))) + { + tree->left->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->left; + } + ret = searchLitOp (tree->left, parent, ops); + if (ret) + return ret; + } + } + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* getResultFromType */ +/*-----------------------------------------------------------------*/ +RESULT_TYPE +getResultTypeFromType (sym_link *type) +{ + /* type = getSpec (type); */ + if (IS_BIT (type)) + return RESULT_TYPE_BIT; + if (IS_BITFIELD (type)) + { + int blen = SPEC_BLEN (type); + + if (blen <= 1) + return RESULT_TYPE_BIT; + if (blen <= 8) + return RESULT_TYPE_CHAR; + return RESULT_TYPE_INT; + } + if (IS_CHAR (type)) + return RESULT_TYPE_CHAR; + if ( IS_INT (type) + && !IS_LONG (type)) + return RESULT_TYPE_INT; + return RESULT_TYPE_OTHER; +} + +/*-----------------------------------------------------------------*/ +/* addCast - adds casts to a type specified by RESULT_TYPE */ +/*-----------------------------------------------------------------*/ +static ast * +addCast (ast *tree, RESULT_TYPE resultType, bool upcast) +{ + sym_link *newLink; + bool upCasted = FALSE; + switch (resultType) + { + case RESULT_TYPE_NONE: + /* char: promote to int */ + if (!upcast || + getSize (tree->etype) >= INTSIZE) + return tree; + newLink = newIntLink(); + upCasted = TRUE; + break; + case RESULT_TYPE_CHAR: + if (getSize (tree->etype) <= 1) + return tree; + newLink = newCharLink(); + break; + case RESULT_TYPE_INT: +#if 0 + if (getSize (tree->etype) > INTSIZE) + { + /* warn ("Loosing significant digits"); */ + return; + } +#endif + /* char: promote to int */ + if (!upcast || + getSize (tree->etype) >= INTSIZE) + return tree; + newLink = newIntLink(); + upCasted = TRUE; + break; + case RESULT_TYPE_OTHER: + if (!upcast) + return tree; + /* return type is long, float: promote char to int */ + if (getSize (tree->etype) >= INTSIZE) + return tree; + newLink = newIntLink(); + upCasted = TRUE; + break; + default: + return tree; + } + tree->decorated = 0; + tree = newNode (CAST, newAst_LINK (newLink), tree); + tree->lineno = tree->right->lineno; + /* keep unsigned type during cast to smaller type, + but not when promoting from char to int */ + if (!upCasted) + SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0; + return decorateType (tree, resultType); +} + +/*-----------------------------------------------------------------*/ +/* resultTypePropagate - decides if resultType can be propagated */ +/*-----------------------------------------------------------------*/ +static RESULT_TYPE +resultTypePropagate (ast *tree, RESULT_TYPE resultType) +{ + switch (tree->opval.op) + { + case '=': + case '?': + case ':': + case '|': + case '^': + case '*': + case '+': + case '-': + case LABEL: + return resultType; + case '&': + if (!tree->right) + /* can be unary */ + return RESULT_TYPE_NONE; + else + return resultType; + case IFX: + return RESULT_TYPE_IFX; + default: + return RESULT_TYPE_NONE; + } } /*-----------------------------------------------------------------*/ -/* decorateType - compute type for this tree also does type cheking */ -/* this is done bottom up, since type have to flow upwards */ -/* it also does constant folding, and paramater checking */ +/* getLeftResultType - gets type from left branch for propagation */ /*-----------------------------------------------------------------*/ +static RESULT_TYPE +getLeftResultType (ast *tree, RESULT_TYPE resultType) +{ + switch (tree->opval.op) + { + case '=': + case CAST: + if (IS_PTR (LTYPE (tree))) + return RESULT_TYPE_NONE; + else + return getResultTypeFromType (LETYPE (tree)); + case RETURN: + if (IS_PTR (currFunc->type->next)) + return RESULT_TYPE_NONE; + else + return getResultTypeFromType (currFunc->type->next); + case '[': + if (!IS_ARRAY (LTYPE (tree))) + return resultType; + if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256) + return RESULT_TYPE_CHAR; + return resultType; + default: + return resultType; + } +} + +/*--------------------------------------------------------------------*/ +/* decorateType - compute type for this tree, also does type checking.*/ +/* This is done bottom up, since type has to flow upwards. */ +/* resultType flows top-down and forces e.g. char-arithmetik, if the */ +/* result is a char and the operand(s) are int's. */ +/* It also does constant folding, and parameter checking. */ +/*--------------------------------------------------------------------*/ ast * -decorateType (ast * tree) +decorateType (ast * tree, RESULT_TYPE resultType) { int parmNumber; sym_link *p; + RESULT_TYPE resultTypeProp; if (!tree) return tree; @@ -1918,7 +2205,7 @@ decorateType (ast * tree) /*------------------------------------------------------------------*/ /*----------------------------*/ - /* leaf has been reached */ +/* leaf has been reached */ /*----------------------------*/ lineno=tree->lineno; /* if this is of type value */ @@ -1982,10 +2269,71 @@ decorateType (ast * tree) { ast *dtl, *dtr; - dtl = decorateType (tree->left); - /* delay right side for '?' operator since conditional macro expansions might - rely on this */ - dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right)); + #if 0 + if (tree->opval.op == NULLOP || tree->opval.op == BLOCK) + { + if (tree->left && tree->left->type == EX_OPERAND + && (tree->left->opval.op == INC_OP + || tree->left->opval.op == DEC_OP) + && tree->left->left) + { + tree->left->right = tree->left->left; + tree->left->left = NULL; + } + if (tree->right && tree->right->type == EX_OPERAND + && (tree->right->opval.op == INC_OP + || tree->right->opval.op == DEC_OP) + && tree->right->left) + { + tree->right->right = tree->right->left; + tree->right->left = NULL; + } + } + #endif + + /* Before decorating the left branch we've to decide in dependence + upon tree->opval.op, if resultType can be propagated */ + resultTypeProp = resultTypePropagate (tree, resultType); + + if (tree->opval.op == '?') + dtl = decorateType (tree->left, RESULT_TYPE_IFX); + else + dtl = decorateType (tree->left, resultTypeProp); + + /* if an array node, we may need to swap branches */ + if (tree->opval.op == '[') + { + /* determine which is the array & which the index */ + if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && + IS_INTEGRAL (LTYPE (tree))) + { + ast *tempTree = tree->left; + tree->left = tree->right; + tree->right = tempTree; + } + } + + /* After decorating the left branch there's type information available + in tree->left->?type. If the op is e.g. '=' we extract the type + information from there and propagate it to the right branch. */ + resultTypeProp = getLeftResultType (tree, resultTypeProp); + + switch (tree->opval.op) + { + case '?': + /* delay right side for '?' operator since conditional macro + expansions might rely on this */ + dtr = tree->right; + break; + case CALL: + /* decorate right side for CALL (parameter list) in processParms(); + there is resultType available */ + dtr = tree->right; + break; + default: + dtr = decorateType (tree->right, resultTypeProp); + break; + } /* this is to take care of situations when the tree gets rewritten */ @@ -1993,26 +2341,8 @@ decorateType (ast * tree) tree->left = dtl; if (dtr != tree->right) tree->right = dtr; - - if (IS_AST_OP(tree) && - (tree->opval.op == CAST || tree->opval.op == '=') && - (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) && - (getSize(RTYPE(tree)) < INTSIZE)) { - // this is a cast/assign to a bigger type - if (IS_AST_OP(tree->right) && - IS_INTEGRAL(tree->right->ftype) && - (tree->right->opval.op == LEFT_OP || - tree->right->opval.op == '*' || - tree->right->opval.op == '+' || - tree->right->opval.op == '-') && - tree->right->right) { - // we should cast an operand instead of the result - tree->right->decorated = 0; - tree->right->left = newNode( CAST, newAst_LINK(newIntLink()), - tree->right->left); - tree->right = decorateType(tree->right); - } - } + if ((dtl && dtl->isError) || (dtr && dtr->isError)) + return tree; } /* depending on type of operator do */ @@ -2025,15 +2355,6 @@ decorateType (ast * tree) /*----------------------------*/ case '[': - /* determine which is the array & which the index */ - if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree))) - { - - ast *tempTree = tree->left; - tree->left = tree->right; - tree->right = tempTree; - } - /* first check if this is a array or a pointer */ if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree)))) { @@ -2054,11 +2375,19 @@ decorateType (ast * tree) werror (E_LVALUE_REQUIRED, "array access"); goto errorTreeReturn; } + + if (IS_LITERAL (RTYPE (tree))) + { + int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree))); + int arraySize = DCL_ELEM (LTYPE (tree)); + if (arraySize && arrayIndex >= arraySize) + { + werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize); + } + } + RRVAL (tree) = 1; COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next); - if (IS_PTR(LTYPE(tree))) { - SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); - } return tree; /*------------------------------------------------------------------*/ @@ -2104,6 +2433,7 @@ decorateType (ast * tree) /* adjust the storage class */ switch (DCL_TYPE(tree->left->ftype)) { case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; break; case FPOINTER: SPEC_SCLS(TETYPE(tree)) = S_XDATA; @@ -2112,6 +2442,7 @@ decorateType (ast * tree) SPEC_SCLS(TETYPE(tree)) = S_CODE; break; case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; break; case PPOINTER: SPEC_SCLS(TETYPE(tree)) = S_XSTACK; @@ -2123,23 +2454,63 @@ decorateType (ast * tree) SPEC_SCLS(TETYPE(tree)) = S_EEPROM; break; case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; case ARRAY: case FUNCTION: break; } - + + /* This breaks with extern declarations, bitfields, and perhaps other */ + /* cases (gcse). Let's leave this optimization disabled for now and */ + /* ponder if there's a safe way to do this. -- EEP */ + #if 0 + if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left) + && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype)) + { + /* If defined struct type at addr var + then rewrite (&struct var)->member + as temp + and define membertype at (addr+offsetof(struct var,member)) temp + */ + symbol *sym; + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)), + AST_SYMBOL(tree->right)); + + sym = newSymbol(genSymName (0), 0); + sym->type = TTYPE (tree); + sym->etype = getSpec(sym->type); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype) + + element->offset; + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + AST_VALUE (tree) = symbolVal(sym); + TLVAL (tree) = 1; + TRVAL (tree) = 0; + tree->type = EX_VALUE; + tree->left = NULL; + tree->right = NULL; + } + #endif + return tree; /*------------------------------------------------------------------*/ /*----------------------------*/ /* ++/-- operation */ /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: case DEC_OP: { sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree)); COPYTYPE (TTYPE (tree), TETYPE (tree), ltc); - if (!tree->initMode && IS_CONSTANT(TETYPE(tree))) + if (!tree->initMode && IS_CONSTANT(TTYPE(tree))) werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--"); if (tree->right) @@ -2188,14 +2559,44 @@ decorateType (ast * tree) ast *otree = optimizeGetHbit (tree); if (otree != tree) - return decorateType (otree); + return decorateType (otree, RESULT_CHECK); } - TTYPE (tree) = - computeType (LTYPE (tree), RTYPE (tree)); + tree->left = addCast (tree->left, resultType, FALSE); + tree->right = addCast (tree->right, resultType, FALSE); + TTYPE (tree) = computeType (LTYPE (tree), + RTYPE (tree), + resultType, + tree->opval.op); TETYPE (tree) = getSpec (TTYPE (tree)); + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a and-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "&"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent, RESULT_CHECK); + } + } + LRVAL (tree) = RRVAL (tree) = 1; + return tree; } @@ -2211,7 +2612,7 @@ decorateType (ast * tree) goto errorTreeReturn; } - if (SPEC_SCLS (tree->left->etype) == S_REGISTER) + if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER) { werror (E_ILLEGAL_ADDR, "address of register variable"); goto errorTreeReturn; @@ -2234,11 +2635,10 @@ decorateType (ast * tree) werror (E_LVALUE_REQUIRED, "address of"); goto errorTreeReturn; } - if (SPEC_SCLS (tree->left->etype) == S_CODE) - { - DCL_TYPE (p) = CPOINTER; - DCL_PTR_CONST (p) = port->mem.code_ro; - } + if (!LETYPE (tree)) + DCL_TYPE (p) = POINTER; + else if (SPEC_SCLS (tree->left->etype) == S_CODE) + DCL_TYPE (p) = CPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XDATA) DCL_TYPE (p) = FPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XSTACK) @@ -2261,10 +2661,24 @@ decorateType (ast * tree) p->next = LTYPE (tree); TTYPE (tree) = p; TETYPE (tree) = getSpec (TTYPE (tree)); - DCL_PTR_CONST (p) = SPEC_CONST (TETYPE (tree)); - DCL_PTR_VOLATILE (p) = SPEC_VOLATILE (TETYPE (tree)); LLVAL (tree) = 1; TLVAL (tree) = 1; + + #if 0 + if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP + && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left)) + { + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)), + AST_SYMBOL(tree->left->right)); + AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left), + valueFromLit(element->offset)); + tree->left = NULL; + tree->right = NULL; + tree->type = EX_VALUE; + tree->values.literalFromCast = 1; + } + #endif + return tree; /*------------------------------------------------------------------*/ @@ -2276,9 +2690,39 @@ decorateType (ast * tree) { ast *wtree = optimizeRRCRLC (tree); if (wtree != tree) - return decorateType (wtree); - // fall through + return decorateType (wtree, RESULT_CHECK); + + wtree = optimizeSWAP (tree); + if (wtree != tree) + return decorateType (wtree, RESULT_CHECK); } + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a or-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "|"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent, RESULT_CHECK); + } + } + /* fall through */ + /*------------------------------------------------------------------*/ /*----------------------------*/ /* bitwise xor */ @@ -2308,10 +2752,43 @@ decorateType (ast * tree) TTYPE (tree) = tree->opval.val->type; return tree; } + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a xor-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) && + tree->opval.op == '^') /* the same source is used by 'bitwise or' */ + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "^"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent, RESULT_CHECK); + } + } + LRVAL (tree) = RRVAL (tree) = 1; + tree->left = addCast (tree->left, resultType, FALSE); + tree->right = addCast (tree->right, resultType, FALSE); TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree))); + RTYPE (tree), + resultType, + tree->opval.op)); + + return tree; /*------------------------------------------------------------------*/ /*----------------------------*/ @@ -2335,10 +2812,46 @@ decorateType (ast * tree) tree->opval.val->type); return tree; } + LRVAL (tree) = RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree))); + RTYPE (tree), + resultType, + tree->opval.op)); + + /* if right is a literal and */ + /* left is also a division by a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "/"); + if (litTree) + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_div */ + litTree->right = newNode ('*', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("1"); + decorateType (parent, RESULT_CHECK); + } + else + { + /* litTree->left is literal: no gcse possible. + We can't call decorateType(parent, RESULT_CHECK), because + this would cause an infinit loop. */ + parent->decorated = 1; + decorateType (litTree, RESULT_CHECK); + } + } + } + return tree; /*------------------------------------------------------------------*/ @@ -2371,7 +2884,9 @@ decorateType (ast * tree) LRVAL (tree) = RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree))); + RTYPE (tree), + resultType, + tree->opval.op)); return tree; /*------------------------------------------------------------------*/ @@ -2392,9 +2907,43 @@ decorateType (ast * tree) werror (E_LVALUE_REQUIRED, "pointer deref"); goto errorTreeReturn; } - TTYPE (tree) = copyLinkChain (LTYPE (tree)->next); - TETYPE (tree) = getSpec (TTYPE (tree)); - SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); + if (IS_ADDRESS_OF_OP(tree->left)) + { + /* replace *&obj with obj */ + return tree->left->left; + } + TTYPE (tree) = copyLinkChain (LTYPE (tree)->next); + TETYPE (tree) = getSpec (TTYPE (tree)); + /* adjust the storage class */ + switch (DCL_TYPE(tree->left->ftype)) { + case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; + break; + case FPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XDATA; + break; + case CPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_CODE; + break; + case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case PPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + break; + case IPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_IDATA; + break; + case EEPPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_EEPROM; + break; + case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case ARRAY: + case FUNCTION: + break; + } return tree; } @@ -2429,16 +2978,31 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* we can find a 2nd literal in a mul-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "*"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent, RESULT_CHECK); + } + } + LRVAL (tree) = RRVAL (tree) = 1; + tree->left = addCast (tree->left, resultType, FALSE); + tree->right = addCast (tree->right, resultType, FALSE); TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree))); - - /* promote result to int if left & right are char - this will facilitate hardware multiplies 8bit x 8bit = 16bit */ - if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) { - SPEC_NOUN(TETYPE(tree)) = V_INT; - } + computeType (LTYPE (tree), + RTYPE (tree), + resultType, + tree->opval.op)); return tree; @@ -2450,7 +3014,7 @@ decorateType (ast * tree) /* if unary plus */ if (!tree->right) { - if (!IS_INTEGRAL (LTYPE (tree))) + if (!IS_ARITHMETIC (LTYPE (tree))) { werror (E_UNARY_OP, '+'); goto errorTreeReturn; @@ -2521,15 +3085,62 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *litTree, *parent; + litTree = searchLitOp (tree, &parent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_aa */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tree->left; + tree->left = tTree; + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_asr */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + } + else + { + /* foo_asl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + litTree->opval.op = '+'; + tree->opval.op = '-'; + } + } + decorateType (parent, RESULT_CHECK); + } + } + LRVAL (tree) = RRVAL (tree) = 1; /* if the left is a pointer */ if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) ) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); else - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree))); + { + tree->left = addCast (tree->left, resultType, TRUE); + tree->right = addCast (tree->right, resultType, TRUE); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType, + tree->opval.op)); + } + return tree; /*------------------------------------------------------------------*/ @@ -2626,15 +3237,63 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); else - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree))); + { + tree->left = addCast (tree->left, resultType, TRUE); + tree->right = addCast (tree->right, resultType, TRUE); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType, + tree->opval.op)); + } + LRVAL (tree) = RRVAL (tree) = 1; + + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0) + { + ast *litTree, *litParent; + litTree = searchLitOp (tree, &litParent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_sa */ + litTree->right = newNode ('-', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_ssr */ + litTree->right = newNode ('+', tree->right, litTree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else + { + /* foo_ssl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + } + } + decorateType (litParent, RESULT_CHECK); + } + } return tree; /*------------------------------------------------------------------*/ /*----------------------------*/ - /* compliment */ + /* complement */ /*----------------------------*/ case '~': /* can be only integral type */ @@ -2690,6 +3349,7 @@ decorateType (ast * tree) /*----------------------------*/ case RRC: case RLC: + case SWAP: TTYPE (tree) = LTYPE (tree); TETYPE (tree) = LETYPE (tree); return tree; @@ -2725,33 +3385,44 @@ decorateType (ast * tree) return tree; } - /* if only the right side is a literal & we are - shifting more than size of the left operand then zero */ - if (IS_LITERAL (RTYPE (tree)) && - ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >= - (getSize (LTYPE (tree)) * 8)) + LRVAL (tree) = RRVAL (tree) = 1; + if (tree->opval.op == LEFT_OP) { - if (tree->opval.op==LEFT_OP || - (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) { - lineno=tree->lineno; - werror (W_SHIFT_CHANGED, - (tree->opval.op == LEFT_OP ? "left" : "right")); - tree->type = EX_VALUE; - tree->left = tree->right = NULL; - tree->opval.val = constVal ("0"); - TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; - return tree; - } + tree->left = addCast (tree->left, resultType, TRUE); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + NULL, + resultType, + tree->opval.op)); } - LRVAL (tree) = RRVAL (tree) = 1; - if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree))) + else /* RIGHT_OP */ { - COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree)); + /* no promotion necessary */ + TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree)); + if (IS_LITERAL (TTYPE (tree))) + SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL; } - else + + /* if only the right side is a literal & we are + shifting more than size of the left operand then zero */ + if (IS_LITERAL (RTYPE (tree)) && + ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >= + (getSize (TETYPE (tree)) * 8)) { - COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); + if (tree->opval.op==LEFT_OP || + (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) + { + lineno=tree->lineno; + werror (W_SHIFT_CHANGED, + (tree->opval.op == LEFT_OP ? "left" : "right")); + tree->type = EX_VALUE; + tree->left = tree->right = NULL; + tree->opval.val = constVal ("0"); + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + return tree; + } } + return tree; /*------------------------------------------------------------------*/ @@ -2765,10 +3436,27 @@ decorateType (ast * tree) werror (E_CAST_ILLEGAL); goto errorTreeReturn; } - + /* make sure the type is complete and sane */ checkTypeSanity(LETYPE(tree), "(cast)"); + /* If code memory is read only, then pointers to code memory */ + /* implicitly point to constants -- make this explicit */ + { + sym_link *t = LTYPE(tree); + while (t && t->next) + { + if (IS_CODEPTR(t) && port->mem.code_ro) + { + if (IS_SPEC(t->next)) + SPEC_CONST (t->next) = 1; + else + DCL_PTR_CONST (t->next) = 1; + } + t = t->next; + } + } + #if 0 /* if the right is a literal replace the tree */ if (IS_LITERAL (RETYPE (tree))) { @@ -2781,10 +3469,10 @@ decorateType (ast * tree) tree->right = NULL; TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && + } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ { sym_link *rest = LTYPE(tree)->next; - werror(W_LITERAL_GENERIC); + werror(W_LITERAL_GENERIC); TTYPE(tree) = newLink(DECLARATOR); DCL_TYPE(TTYPE(tree)) = FPOINTER; TTYPE(tree)->next = rest; @@ -2803,27 +3491,117 @@ decorateType (ast * tree) /* if pointer to struct then check names */ if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) && IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) && - strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) + strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) { werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag, SPEC_STRUCT(LETYPE(tree))->tag); } #endif - /* if the right is a literal replace the tree */ - if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree))) { - tree->type = EX_VALUE; + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_SYM_VALUE (tree->right->left) + && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) { + + tree->type = EX_VALUE; tree->opval.val = valCastLiteral (LTYPE (tree), - floatFromVal (valFromType (RETYPE (tree)))); + SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype)); + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); tree->left = NULL; tree->right = NULL; - TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else { - TTYPE (tree) = LTYPE (tree); - LRVAL (tree) = 1; + return tree; + } + + /* handle offsetof macro: */ + /* #define offsetof(TYPE, MEMBER) \ */ + /* ((unsigned) &((TYPE *)0)->MEMBER) */ + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_OP (tree->right->left) + && tree->right->left->opval.op == PTR_OP + && IS_AST_OP (tree->right->left->left) + && tree->right->left->left->opval.op == CAST + && IS_AST_LIT_VALUE(tree->right->left->left->right)) { + + symbol *element = getStructElement ( + SPEC_STRUCT (LETYPE(tree->right->left)), + AST_SYMBOL(tree->right->left->right) + ); + + if (element) { + tree->type = EX_VALUE; + tree->opval.val = valCastLiteral ( + LTYPE (tree), + element->offset + + floatFromVal (valFromType (RTYPE (tree->right->left->left))) + ); + + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); + tree->left = NULL; + tree->right = NULL; + return tree; + } } -#endif + + /* if the right is a literal replace the tree */ + if (IS_LITERAL (RETYPE (tree))) { + #if 0 + if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) { + /* rewrite (type *)litaddr + as &temp + and define type at litaddr temp + (but only if type's storage class is not generic) + */ + ast *newTree = newNode ('&', NULL, NULL); + symbol *sym; + + TTYPE (newTree) = LTYPE (tree); + TETYPE (newTree) = getSpec(LTYPE (tree)); + + /* define a global symbol at the casted address*/ + sym = newSymbol(genSymName (0), 0); + sym->type = LTYPE (tree)->next; + if (!sym->type) + sym->type = newLink (V_VOID); + sym->etype = getSpec(sym->type); + SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree)); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree))); + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + newTree->left = newAst_VALUE(symbolVal(sym)); + newTree->left->lineno = tree->lineno; + LTYPE (newTree) = sym->type; + LETYPE (newTree) = sym->etype; + LLVAL (newTree) = 1; + LRVAL (newTree) = 0; + TLVAL (newTree) = 1; + return newTree; + } + #endif + if (!IS_PTR (LTYPE (tree))) { + tree->type = EX_VALUE; + tree->opval.val = + valCastLiteral (LTYPE (tree), + floatFromVal (valFromType (RTYPE (tree)))); + TTYPE (tree) = tree->opval.val->type; + tree->left = NULL; + tree->right = NULL; + tree->values.literalFromCast = 1; + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + } + } + TTYPE (tree) = LTYPE (tree); + LRVAL (tree) = 1; + +#endif TETYPE (tree) = getSpec (TTYPE (tree)); return tree; @@ -2856,8 +3634,8 @@ decorateType (ast * tree) IS_LITERAL (LTYPE (tree))) { tree->type = EX_VALUE; - tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)), - valFromType (RETYPE (tree)), + tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)), + valFromType (RTYPE (tree)), tree->opval.op); tree->right = tree->left = NULL; TETYPE (tree) = getSpec (TTYPE (tree) = @@ -2888,7 +3666,7 @@ decorateType (ast * tree) /* if they are pointers they must be castable */ if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) { - if (tree->opval.op==EQ_OP && + if (tree->opval.op==EQ_OP && !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) { // we cannot cast a gptr to a !gptr: switch the leaves struct ast *s=tree->left; @@ -2898,7 +3676,7 @@ decorateType (ast * tree) if (compareType (LTYPE (tree), RTYPE (tree)) == 0) { werror (E_COMPARE_OP); - fprintf (stderr, "comparring type "); + fprintf (stderr, "comparing type "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, "to type "); printTypeChain (RTYPE (tree), stderr); @@ -2924,17 +3702,35 @@ decorateType (ast * tree) } } /* if unsigned value < 0 then always false */ - /* if (unsigned value) > 0 then (unsigned value) */ - if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) && - ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) { - - if (tree->opval.op == '<') { + /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */ + if (SPEC_USIGN(LETYPE(tree)) && + !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */ + IS_LITERAL(RTYPE(tree)) && + ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) + { + if (tree->opval.op == '<') + { return tree->right; - } - if (tree->opval.op == '>') { - return tree->left; - } - } + } + if (tree->opval.op == '>') + { + if (resultType == RESULT_TYPE_IFX) + { + /* the parent is an ifx: */ + /* if (unsigned value) */ + return tree->left; + } + + /* (unsigned value) ? 1 : 0 */ + tree->opval.op = '?'; + tree->right = newNode (':', + newAst_VALUE (constVal ("1")), + tree->right); /* val 0 */ + tree->right->lineno = tree->lineno; + tree->right->left->lineno = tree->lineno; + decorateType (tree->right, RESULT_CHECK); + } + } /* if they are both literal then */ /* rewrite the tree */ if (IS_LITERAL (RTYPE (tree)) && @@ -2959,8 +3755,13 @@ decorateType (ast * tree) /*----------------------------*/ case SIZEOF: /* evaluate wihout code generation */ /* change the type to a integer */ + { + int size = getSize (tree->right->ftype); + SNPRINTF(buffer, sizeof(buffer), "%d", size); + if (!size && !IS_VOID(tree->right->ftype)) + werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE); + } tree->type = EX_VALUE; - SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype))); tree->opval.val = constVal (buffer); tree->right = tree->left = NULL; TETYPE (tree) = getSpec (TTYPE (tree) = @@ -2994,6 +3795,9 @@ decorateType (ast * tree) case V_STRUCT: typeofv = TYPEOF_STRUCT; break; + case V_BITFIELD: + typeofv = TYPEOF_BITFIELD; + break; case V_BIT: typeofv = TYPEOF_BIT; break; @@ -3046,20 +3850,22 @@ decorateType (ast * tree) /*----------------------------*/ case '?': /* the type is value of the colon operator (on the right) */ - assert(IS_COLON_OP(tree->right)); + assert (IS_COLON_OP (tree->right)); /* if already known then replace the tree : optimizer will do it but faster to do it here */ - if (IS_LITERAL (LTYPE(tree))) { - if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) { - return decorateType(tree->right->left) ; - } else { - return decorateType(tree->right->right) ; - } - } else { - tree->right = decorateType(tree->right); - TTYPE (tree) = RTYPE(tree); + if (IS_LITERAL (LTYPE (tree))) + { + if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) + return decorateType (tree->right->left, resultTypeProp); + else + return decorateType (tree->right->right, resultTypeProp); + } + else + { + tree->right = decorateType (tree->right, resultTypeProp); + TTYPE (tree) = RTYPE (tree); TETYPE (tree) = getSpec (TTYPE (tree)); - } + } return tree; case ':': @@ -3070,7 +3876,8 @@ decorateType (ast * tree) goto errorTreeReturn; } - TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree)); + TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), + resultType, tree->opval.op); TETYPE (tree) = getSpec (TTYPE (tree)); return tree; @@ -3093,11 +3900,11 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); if (!tree->initMode && IS_CONSTANT (LTYPE (tree))) - werror (E_CODE_WRITE, *tree->opval.op==MUL_ASSIGN ? "*=" : "/="); + werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, *tree->opval.op==MUL_ASSIGN ? "*=" : "/="); + werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); goto errorTreeReturn; } LLVAL (tree) = 1; @@ -3152,7 +3959,9 @@ decorateType (ast * tree) RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree))); + RTYPE (tree), + RESULT_TYPE_NOPROM, + tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) werror (E_CODE_WRITE, "-="); @@ -3193,7 +4002,9 @@ decorateType (ast * tree) RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree))); + RTYPE (tree), + RESULT_TYPE_NOPROM, + tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) werror (E_CODE_WRITE, "+="); @@ -3204,7 +4015,7 @@ decorateType (ast * tree) goto errorTreeReturn; } - tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right)); + tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK); tree->opval.op = '='; return tree; @@ -3242,7 +4053,7 @@ decorateType (ast * tree) RRVAL (tree) = 1; LLVAL (tree) = 1; if (!tree->initMode ) { - if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree)))) + if (IS_CONSTANT(LTYPE(tree))) werror (E_CODE_WRITE, "="); } if (LRVAL (tree)) @@ -3266,26 +4077,45 @@ decorateType (ast * tree) /* function call */ /*----------------------------*/ case CALL: - parmNumber = 1; - - if (processParms (tree->left, - FUNC_ARGS(tree->left->ftype), - tree->right, &parmNumber, TRUE)) { - goto errorTreeReturn; - } + + /* undo any explicit pointer derefernce; PCALL will handle it instead */ + if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP) + { + if (tree->left->opval.op == '*' && !tree->left->right) + tree->left = tree->left->left; + } - if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && - !IFFUNC_ISBUILTIN(LTYPE(tree))) + /* require a function or pointer to function */ + if (!IS_FUNC (LTYPE (tree)) + && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next))) { - reverseParms (tree->right); + werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED); + goto errorTreeReturn; } - if (IS_CODEPTR(LTYPE(tree))) { - TTYPE(tree) = LTYPE(tree)->next->next; - } else { - TTYPE(tree) = LTYPE(tree)->next; + { + sym_link *functype; + parmNumber = 1; + + if (IS_CODEPTR(LTYPE(tree))) + functype = LTYPE (tree)->next; + else + functype = LTYPE (tree); + + if (processParms (tree->left, FUNC_ARGS(functype), + tree->right, &parmNumber, TRUE)) { + goto errorTreeReturn; + } + + if ((options.stackAuto || IFFUNC_ISREENT (functype)) && + !IFFUNC_ISBUILTIN(functype)) + { + reverseParms (tree->right); + } + + TTYPE (tree) = functype->next; + TETYPE (tree) = getSpec (TTYPE (tree)); } - TETYPE (tree) = getSpec (TTYPE (tree)); return tree; /*------------------------------------------------------------------*/ @@ -3298,7 +4128,7 @@ decorateType (ast * tree) if (compareType (currFunc->type->next, RTYPE (tree)) == 0) { - werror (W_RETURN_MISMATCH); + werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH); printFromToType (RTYPE(tree), currFunc->type->next); goto errorTreeReturn; } @@ -3307,17 +4137,18 @@ decorateType (ast * tree) && tree->right && !IS_VOID (RTYPE (tree))) { - werror (E_FUNC_VOID); + werrorfl (tree->filename, tree->lineno, E_FUNC_VOID); goto errorTreeReturn; } - /* if there is going to be a casing required then add it */ + /* if there is going to be a casting required then add it */ if (compareType (currFunc->type->next, RTYPE (tree)) < 0) { tree->right = decorateType (newNode (CAST, - newAst_LINK (copyLinkChain (currFunc->type->next)), - tree->right)); + newAst_LINK (copyLinkChain (currFunc->type->next)), + tree->right), + RESULT_CHECK); } RRVAL (tree) = 1; @@ -3342,7 +4173,7 @@ decorateType (ast * tree) /* the switch value must be an integer */ if (!IS_INTEGRAL (LTYPE (tree))) { - werror (E_SWITCH_NON_INTEGER); + werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER); goto errorTreeReturn; } LRVAL (tree) = 1; @@ -3366,9 +4197,9 @@ decorateType (ast * tree) /*----------------------------*/ case FOR: - decorateType (resolveSymbols (AST_FOR (tree, initExpr))); - decorateType (resolveSymbols (AST_FOR (tree, condExpr))); - decorateType (resolveSymbols (AST_FOR (tree, loopExpr))); + decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK); + decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK); + decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK); /* if the for loop is reversible then reverse it otherwise do what we normally @@ -3387,8 +4218,13 @@ decorateType (ast * tree) AST_FOR (tree, initExpr), AST_FOR (tree, condExpr), AST_FOR (tree, loopExpr), - tree->left)); + tree->left), RESULT_CHECK); } + case PARAM: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "node PARAM shouldn't be processed here"); + /* but in processParams() */ + return tree; default: TTYPE (tree) = TETYPE (tree) = NULL; return tree; @@ -3410,12 +4246,15 @@ value * sizeofOp (sym_link * type) { char buff[10]; + int size; /* make sure the type is complete and sane */ checkTypeSanity(type, "(sizeof)"); /* get the size and convert it to character */ - SNPRINTF (buff, sizeof(buff), "%d", getSize (type)); + SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type)); + if (!size && !IS_VOID(type)) + werror (E_SIZEOF_INCOMPLETE_TYPE); /* now convert into value */ return constVal (buff); @@ -3599,22 +4438,22 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) /* then case is out of context */ if (!swStat) { - werror (E_CASE_CONTEXT); + werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT); return NULL; } - caseVal = decorateType (resolveSymbols (caseVal)); + caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK); /* if not a constant then error */ if (!IS_LITERAL (caseVal->ftype)) { - werror (E_CASE_CONSTANT); + werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT); return NULL; } /* if not a integer than error */ if (!IS_INTEGRAL (caseVal->ftype)) { - werror (E_CASE_NON_INTEGER); + werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER); return NULL; } @@ -3637,6 +4476,12 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) { pval->next = caseVal->opval.val; } + else if ((int) floatFromVal (val) == cVal) + { + werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL, + "case"); + return NULL; + } else { /* we found a value greater than */ @@ -3669,7 +4514,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) /* createDefault - creates the parse tree for the default statement */ /*-----------------------------------------------------------------*/ ast * -createDefault (ast * swStat, ast * stmnt) +createDefault (ast * swStat, ast * defaultVal, ast * stmnt) { char defLbl[SDCC_NAME_MAX + 1]; @@ -3677,7 +4522,14 @@ createDefault (ast * swStat, ast * stmnt) /* then case is out of context */ if (!swStat) { - werror (E_CASE_CONTEXT); + werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT); + return NULL; + } + + if (swStat->values.switchVals.swDefault) + { + werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL, + "default"); return NULL; } @@ -3942,8 +4794,13 @@ optimizeGetHbit (ast * tree) if ((i = (int) AST_LIT_VALUE (tree->left->right)) != (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) return tree; + + /* make sure the port supports GETHBIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) + return tree; - return decorateType (newNode (GETHBIT, tree->left->left, NULL)); + return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK); } @@ -3994,6 +4851,11 @@ optimizeRRCRLC (ast * root) (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext0; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); } @@ -4024,6 +4886,11 @@ tryNext0: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext1; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); @@ -4055,6 +4922,11 @@ tryNext1: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext2; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -4085,6 +4957,11 @@ tryNext2: (getSize (TTYPE (root->left->left)) * 8 - 1)) return root; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -4094,6 +4971,61 @@ tryNext2: return root; } +/*-----------------------------------------------------------------*/ +/* optimizeSWAP :- optimize for nibble/byte/word swaps */ +/*-----------------------------------------------------------------*/ +ast * +optimizeSWAP (ast * root) +{ + /* will look for trees of the form + (?expr << 4) | (?expr >> 4) or + (?expr >> 4) | (?expr << 4) will make that + into a SWAP : operation .. + note : by 4 I mean (number of bits required to hold the + variable /2 ) */ + /* if the root operations is not a | operation the not */ + if (!IS_BITOR (root)) + return root; + + /* (?expr << 4) | (?expr >> 4) */ + if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right)) + || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right))) + { + + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; + + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + return root; + + /* make sure it is the same expression */ + if (!isAstEqual (root->left->left, + root->right->left)) + return root; + + if (AST_LIT_VALUE (root->left->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + if (AST_LIT_VALUE (root->right->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + /* make sure the port supports SWAP */ + if (port->hasExtBitOp + && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left)))) + return root; + + /* found it : create the AST */ + return newNode (SWAP, root->left->left, NULL); + } + + + /* not found return root */ + return root; +} + /*-----------------------------------------------------------------*/ /* optimizeCompare - otimizes compares for bit variables */ /*-----------------------------------------------------------------*/ @@ -4135,7 +5067,7 @@ optimizeCompare (ast * root) break; } - return decorateType (optExpr); + return decorateType (optExpr, RESULT_CHECK); } vleft = (root->left->type == EX_VALUE ? @@ -4209,7 +5141,7 @@ optimizeCompare (ast * root) break; } } - return decorateType (resolveSymbols (optExpr)); + return decorateType (resolveSymbols (optExpr), RESULT_CHECK); } /* end-of-if of BITVAR */ noOptimize: @@ -4355,7 +5287,8 @@ createFunction (symbol * name, ast * body) SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name); body = resolveSymbols (body); /* resolve the symbols */ - body = decorateType (body); /* propagateType & do semantic checks */ + body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */ + ex = newAst_VALUE (symbolVal (name)); /* create name */ ex = newNode (FUNCTION, ex, body); @@ -4386,7 +5319,7 @@ createFunction (symbol * name, ast * body) { GcurMemmap = statsg; codeOutFile = statsg->oFile; - eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos)))); + eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK))); staticAutos = NULL; } @@ -4409,7 +5342,7 @@ skipall: addSet (&operKeyReset, name); applyToSet (operKeyReset, resetParmKey); - if (options.debug) + if (options.debug) cdbStructBlock(1); cleanUpLevel (LabelTab, 0); @@ -4429,7 +5362,7 @@ skipall: void ast_print (ast * tree, FILE *outfile, int indent) { - + if (!tree) return ; /* can print only decorated trees */ @@ -4442,7 +5375,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"ERROR_NODE(%p)\n",tree); } - + /* print the line */ /* if not block & function */ if (tree->type == EX_OP && @@ -4450,11 +5383,11 @@ void ast_print (ast * tree, FILE *outfile, int indent) tree->opval.op != BLOCK && tree->opval.op != NULLOP)) { } - + if (tree->opval.op == FUNCTION) { int arg=0; value *args=FUNC_ARGS(tree->left->opval.val->type); - fprintf(outfile,"FUNCTION (%s=%p) type (", + fprintf(outfile,"FUNCTION (%s=%p) type (", tree->left->opval.val->name, tree); printTypeChain (tree->left->opval.val->type->next,outfile); fprintf(outfile,") args ("); @@ -4481,8 +5414,8 @@ void ast_print (ast * tree, FILE *outfile, int indent) decls->name, decls); printTypeChain(decls->type,outfile); fprintf(outfile,")\n"); - - decls = decls->next; + + decls = decls->next; } ast_print(tree->right,outfile,indent+2); INDENT(indent,outfile); @@ -4504,11 +5437,14 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* just get the type */ if (tree->type == EX_VALUE) { - if (IS_LITERAL (tree->opval.val->etype)) { - fprintf(outfile,"CONSTANT (%p) value = %d, 0x%x, %g", tree, - (int) floatFromVal(tree->opval.val), - (int) floatFromVal(tree->opval.val), - floatFromVal(tree->opval.val)); + if (IS_LITERAL (tree->opval.val->etype)) { + fprintf(outfile,"CONSTANT (%p) value = ", tree); + if (SPEC_USIGN (tree->opval.val->etype)) + fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val)); + else + fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val)); + fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val), + floatFromVal(tree->opval.val)); } else if (tree->opval.val->sym) { /* if the undefined flag is set then give error message */ if (tree->opval.val->sym->undefined) { @@ -4539,7 +5475,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* depending on type of operator do */ - + switch (tree->opval.op) { /*------------------------------------------------------------------*/ /*----------------------------*/ @@ -4581,25 +5517,35 @@ void ast_print (ast * tree, FILE *outfile, int indent) /*----------------------------*/ /* ++/-- operation */ /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"INC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postincrement case */ + ast_print(tree->right,outfile,indent+2); /* preincrement case */ return ; case DEC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"DEC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postdecrement case */ + ast_print(tree->right,outfile,indent+2); /* predecrement case */ return ; /*------------------------------------------------------------------*/ /*----------------------------*/ /* bitwise and */ /*----------------------------*/ - case '&': + case '&': if (tree->right) { fprintf(outfile,"& (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -4635,7 +5581,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->left,outfile,indent+2); ast_print(tree->right,outfile,indent+2); return ; - + /*------------------------------------------------------------------*/ /*----------------------------*/ /* division */ @@ -4765,6 +5711,12 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); return ; + case SWAP: + fprintf(outfile,"SWAP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; case GETHBIT: fprintf(outfile,"GETHBIT (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -4885,7 +5837,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->left,outfile,indent+2); ast_print(tree->right,outfile,indent+2); return ; - + /*------------------------------------------------------------------*/ /*----------------------------*/ /* assignment operators */ @@ -5091,6 +6043,9 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"FOR LOOP BODY \n"); ast_print(tree->left,outfile,indent+2); return ; + case CRITICAL: + fprintf(outfile,"CRITICAL (%p) \n",tree); + ast_print(tree->left,outfile,indent+2); default: return ; } @@ -5100,3 +6055,29 @@ void PA(ast *t) { ast_print(t,stdout,0); } + + + +/*-----------------------------------------------------------------*/ +/* astErrors : returns non-zero if errors present in tree */ +/*-----------------------------------------------------------------*/ +int astErrors(ast *t) +{ + int errors=0; + + if (t) + { + if (t->isError) + errors++; + + if (t->type == EX_VALUE + && t->opval.val->sym + && t->opval.val->sym->undefined) + errors++; + + errors += astErrors(t->left); + errors += astErrors(t->right); + } + + return errors; +}