X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCast.c;h=441bedc9105bed4feccc0f20c93d5192574fbd07;hb=92c02b20c217e7cf8cc20d667816fdc4c71b9e99;hp=fffd3b8a4434008149b6fbec18a3d12856cffd6b;hpb=38e0883c523938d625978ce83bede44bc744cd8d;p=fw%2Fsdcc diff --git a/src/SDCCast.c b/src/SDCCast.c index fffd3b8a..441bedc9 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -7,29 +7,28 @@ under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! + what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ #include "common.h" -#include "newalloc.h" -int currLineno = 0; -set *astList = NULL ; +int currLineno = 0; +set *astList = NULL; set *operKeyReset = NULL; ast *staticAutos = NULL; -int labelKey = 1 ; +int labelKey = 1; #define LRVAL(x) x->left->rvalue #define RRVAL(x) x->right->rvalue @@ -46,416 +45,458 @@ int labelKey = 1 ; #define ALLOCATE 1 #define DEALLOCATE 2 -char buffer[1024]; int noLineno = 0; -int noAlloc = 0 ; -symbol *currFunc ; -ast *createIval (ast *, sym_link *, initList *, ast *); +int noAlloc = 0; +symbol *currFunc; +ast *createIval (ast *, sym_link *, initList *, ast *); ast *createIvalCharPtr (ast *, sym_link *, ast *); -ast *optimizeRRCRLC ( ast * ); -ast *optimizeGetHbit(ast *); -ast *backPatchLabels (ast *,symbol *,symbol *); -int inInitMode = 0; -FILE *codeOutFile ; -int ptt(ast *tree) { - printTypeChain(tree->ftype,stdout); - return 0; +ast *optimizeRRCRLC (ast *); +ast *optimizeGetHbit (ast *); +ast *backPatchLabels (ast *, symbol *, symbol *); +void PA(ast *t); +int inInitMode = 0; +memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */ +FILE *codeOutFile; +int +ptt (ast * tree) +{ + printTypeChain (tree->ftype, stdout); + return 0; } - + /*-----------------------------------------------------------------*/ /* newAst - creates a fresh node for an expression tree */ /*-----------------------------------------------------------------*/ #if 0 -ast *newAst (int type, void *op ) +ast * +newAst (int type, void *op) { - ast *ex ; - static int oldLineno = 0 ; - - Safe_calloc(ex,sizeof(ast)); - - ex->type = type ; - ex->lineno = (noLineno ? oldLineno : yylineno); - ex->filename = currFname ; - ex->level = NestLevel ; - ex->block = currBlockno ; - ex->initMode = inInitMode; - - /* depending on the type */ - switch (type) { - case EX_VALUE : - ex->opval.val = (value *) op; - break ; - case EX_OP : - ex->opval.op = (long) op ; - break ; - case EX_LINK : - ex->opval.lnk = (sym_link *) op; - break ; - case EX_STMNT : - ex->opval.stmnt= (unsigned) op; - } - - return ex; + ast *ex; + static int oldLineno = 0; + + ex = Safe_alloc ( sizeof (ast)); + + ex->type = type; + ex->lineno = (noLineno ? oldLineno : yylineno); + ex->filename = currFname; + ex->level = NestLevel; + ex->block = currBlockno; + ex->initMode = inInitMode; + + /* depending on the type */ + switch (type) + { + case EX_VALUE: + ex->opval.val = (value *) op; + break; + case EX_OP: + ex->opval.op = (long) op; + break; + case EX_LINK: + ex->opval.lnk = (sym_link *) op; + break; + case EX_STMNT: + ex->opval.stmnt = (unsigned) op; + } + + return ex; } #endif -static ast* newAst_(unsigned type) +static ast * +newAst_ (unsigned type) { - ast *ex ; - static int oldLineno = 0 ; - - ex = Safe_calloc(sizeof(ast)); - - ex->type = type ; - ex->lineno = (noLineno ? oldLineno : yylineno); - ex->filename = currFname ; - ex->level = NestLevel ; - ex->block = currBlockno ; - ex->initMode = inInitMode; - return ex; + ast *ex; + static int oldLineno = 0; + + ex = Safe_alloc ( sizeof (ast)); + + ex->type = type; + ex->lineno = (noLineno ? oldLineno : yylineno); + ex->filename = currFname; + ex->level = NestLevel; + ex->block = currBlockno; + ex->initMode = inInitMode; + return ex; } -ast* newAst_VALUE(value*val) +ast * +newAst_VALUE (value * val) { - ast* ex = newAst_(EX_VALUE); - ex->opval.val = val; - return ex; + ast *ex = newAst_ (EX_VALUE); + ex->opval.val = val; + return ex; } -ast* newAst_OP(unsigned op) +ast * +newAst_OP (unsigned op) { - ast*ex = newAst_(EX_OP); - ex->opval.op = op; - return ex; + ast *ex = newAst_ (EX_OP); + ex->opval.op = op; + return ex; } -ast* newAst_LINK(sym_link*val) +ast * +newAst_LINK (sym_link * val) { - ast* ex = newAst_(EX_LINK); - ex->opval.lnk = val; - return ex; + ast *ex = newAst_ (EX_LINK); + ex->opval.lnk = val; + return ex; } -ast* newAst_STMNT(unsigned val) +ast * +newAst_STMNT (unsigned val) { - ast* ex = newAst_(EX_STMNT); - ex->opval.stmnt = val; - return ex; + ast *ex = newAst_ (EX_STMNT); + ex->opval.stmnt = val; + return ex; } /*-----------------------------------------------------------------*/ /* newNode - creates a new node */ /*-----------------------------------------------------------------*/ -ast *newNode ( long op, ast *left, ast *right ) +ast * +newNode (long op, ast * left, ast * right) { - ast *ex ; - - ex = newAst_OP(op) ; - ex->left = left ; - ex->right = right; - - return ex ; + ast *ex; + + ex = newAst_OP (op); + ex->left = left; + ex->right = right; + + return ex; } /*-----------------------------------------------------------------*/ /* newIfxNode - creates a new Ifx Node */ /*-----------------------------------------------------------------*/ -ast *newIfxNode (ast *condAst, symbol *trueLabel, symbol *falseLabel) +ast * +newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel) { - ast *ifxNode ; - - /* if this is a literal then we already know the result */ - if (condAst->etype && IS_LITERAL(condAst->etype)) { - - /* then depending on the expression value */ - if ( floatFromVal(condAst->opval.val) ) - ifxNode = newNode(GOTO, - newAst_VALUE(symbolVal(trueLabel)), - NULL); - else - ifxNode = newNode(GOTO, - newAst_VALUE(symbolVal(falseLabel)), - NULL); + ast *ifxNode; + + /* if this is a literal then we already know the result */ + if (condAst->etype && IS_LITERAL (condAst->etype)) + { + /* then depending on the expression value */ + if (floatFromVal (condAst->opval.val)) + ifxNode = newNode (GOTO, + newAst_VALUE (symbolVal (trueLabel)), + NULL); + else + ifxNode = newNode (GOTO, + newAst_VALUE (symbolVal (falseLabel)), + NULL); } - else { - ifxNode = newNode(IFX,condAst,NULL); - ifxNode->trueLabel = trueLabel; - ifxNode->falseLabel= falseLabel; + else + { + ifxNode = newNode (IFX, condAst, NULL); + ifxNode->trueLabel = trueLabel; + ifxNode->falseLabel = falseLabel; } - - return ifxNode ; + + return ifxNode; } /*-----------------------------------------------------------------*/ -/* copyAstValues - copies value portion of ast if needed */ +/* copyAstValues - copies value portion of ast if needed */ /*-----------------------------------------------------------------*/ -void copyAstValues (ast *dest,ast *src) +void +copyAstValues (ast * dest, ast * src) { - switch (src->opval.op) { + switch (src->opval.op) + { case BLOCK: - dest->values.sym = copySymbolChain(src->values.sym); - break; - + dest->values.sym = copySymbolChain (src->values.sym); + break; + case SWITCH: - dest->values.switchVals.swVals = - copyValue(src->values.switchVals.swVals); - dest->values.switchVals.swDefault = - src->values.switchVals.swDefault ; - dest->values.switchVals.swNum = - src->values.switchVals.swNum ; - break ; - + dest->values.switchVals.swVals = + copyValue (src->values.switchVals.swVals); + dest->values.switchVals.swDefault = + src->values.switchVals.swDefault; + dest->values.switchVals.swNum = + src->values.switchVals.swNum; + break; + case INLINEASM: - dest->values.inlineasm = Safe_calloc(strlen(src->values.inlineasm)+1); - strcpy(dest->values.inlineasm,src->values.inlineasm); + dest->values.inlineasm = Safe_alloc (strlen (src->values.inlineasm) + 1); + strcpy (dest->values.inlineasm, src->values.inlineasm); + break; + 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)); - AST_FOR(dest,falseLabel) = copySymbol(AST_FOR(src,falseLabel)); - AST_FOR(dest,condLabel) = copySymbol(AST_FOR(src,condLabel)); - AST_FOR(dest,initExpr) = copyAst (AST_FOR(src,initExpr)) ; - AST_FOR(dest,condExpr) = copyAst (AST_FOR(src,condExpr)) ; - AST_FOR(dest,loopExpr) = copyAst (AST_FOR(src,loopExpr)) ; - } - + AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel)); + AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel)); + AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel)); + AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel)); + AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr)); + AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr)); + AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr)); + } + } /*-----------------------------------------------------------------*/ /* copyAst - makes a copy of a given astession */ /*-----------------------------------------------------------------*/ -ast *copyAst (ast *src) +ast * +copyAst (ast * src) { - ast *dest; - - if (!src) return NULL ; - - dest = Safe_calloc(sizeof(ast)); - - dest->type = src->type ; - dest->lineno = src->lineno ; - dest->level = src->level ; - dest->funcName = src->funcName; - dest->argSym = src->argSym; - - /* if this is a leaf */ - /* if value */ - if (src->type == EX_VALUE) { - dest->opval.val = copyValue(src->opval.val); - goto exit; - } - - /* if link */ - if (src->type == EX_LINK) { - dest->opval.lnk = copyLinkChain(src->opval.lnk); - goto exit ; - } - - dest->opval.op = src->opval.op ; - - /* if this is a node that has special values */ - copyAstValues (dest,src); - - if ( src->ftype ) - dest->etype = getSpec(dest->ftype = copyLinkChain(src->ftype)) ; - - dest->trueLabel = copySymbol (src->trueLabel); - dest->falseLabel= copySymbol (src->falseLabel); - dest->left = copyAst(src->left); - dest->right= copyAst(src->right); - exit: - return dest ; - + ast *dest; + + if (!src) + return NULL; + + dest = Safe_alloc ( sizeof (ast)); + + dest->type = src->type; + dest->lineno = src->lineno; + dest->level = src->level; + dest->funcName = src->funcName; + + if (src->ftype) + dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype)); + + /* if this is a leaf */ + /* if value */ + if (src->type == EX_VALUE) + { + dest->opval.val = copyValue (src->opval.val); + goto exit; + } + + /* if link */ + if (src->type == EX_LINK) + { + dest->opval.lnk = copyLinkChain (src->opval.lnk); + goto exit; + } + + dest->opval.op = src->opval.op; + + /* if this is a node that has special values */ + copyAstValues (dest, src); + + dest->trueLabel = copySymbol (src->trueLabel); + dest->falseLabel = copySymbol (src->falseLabel); + dest->left = copyAst (src->left); + dest->right = copyAst (src->right); +exit: + return dest; + } /*-----------------------------------------------------------------*/ /* hasSEFcalls - returns TRUE if tree has a function call */ /*-----------------------------------------------------------------*/ -bool hasSEFcalls ( ast *tree) +bool +hasSEFcalls (ast * tree) { - if (!tree) - return FALSE ; - - if (tree->type == EX_OP && - ( tree->opval.op == CALL || - tree->opval.op == PCALL || - tree->opval.op == '=' || - tree->opval.op == INC_OP || - tree->opval.op == DEC_OP )) - return TRUE; + if (!tree) + return FALSE; - return ( hasSEFcalls(tree->left) | - hasSEFcalls(tree->right)); + if (tree->type == EX_OP && + (tree->opval.op == CALL || + tree->opval.op == PCALL || + tree->opval.op == '=' || + tree->opval.op == INC_OP || + tree->opval.op == DEC_OP)) + return TRUE; + + return (hasSEFcalls (tree->left) | + hasSEFcalls (tree->right)); } /*-----------------------------------------------------------------*/ /* isAstEqual - compares two asts & returns 1 if they are equal */ /*-----------------------------------------------------------------*/ -int isAstEqual (ast *t1, ast *t2) +int +isAstEqual (ast * t1, ast * t2) { - if (!t1 && !t2) - return 1; + if (!t1 && !t2) + return 1; - if (!t1 || !t2) - return 0; + if (!t1 || !t2) + return 0; - /* match type */ - if (t1->type != t2->type) - return 0; + /* match type */ + if (t1->type != t2->type) + return 0; - switch (t1->type) { + switch (t1->type) + { case EX_OP: - if (t1->opval.op != t2->opval.op) - return 0; - return ( isAstEqual(t1->left,t2->left) && - isAstEqual(t1->right,t2->right)); - break; + if (t1->opval.op != t2->opval.op) + return 0; + return (isAstEqual (t1->left, t2->left) && + isAstEqual (t1->right, t2->right)); + break; case EX_VALUE: - if (t1->opval.val->sym) { - if (!t2->opval.val->sym) - return 0; - else - return isSymbolEqual(t1->opval.val->sym, - t2->opval.val->sym); - } - else { - if (t2->opval.val->sym) - return 0; - else - return (floatFromVal(t1->opval.val) == - floatFromVal(t2->opval.val)); + if (t1->opval.val->sym) + { + if (!t2->opval.val->sym) + return 0; + else + return isSymbolEqual (t1->opval.val->sym, + t2->opval.val->sym); } - break; + else + { + if (t2->opval.val->sym) + return 0; + else + return (floatFromVal (t1->opval.val) == + floatFromVal (t2->opval.val)); + } + break; - /* only compare these two types */ - default : - return 0; + /* only compare these two types */ + default: + return 0; } - return 0; + return 0; } /*-----------------------------------------------------------------*/ /* resolveSymbols - resolve symbols from the symbol table */ /*-----------------------------------------------------------------*/ -ast *resolveSymbols (ast *tree) +ast * +resolveSymbols (ast * tree) { - /* walk the entire tree and check for values */ - /* with symbols if we find one then replace */ - /* symbol with that from the symbol table */ - - if ( tree == NULL ) - return tree ; - - /* print the line */ - /* if not block & function */ - if ( tree->type == EX_OP && - ( tree->opval.op != FUNCTION && - tree->opval.op != BLOCK && - tree->opval.op != NULLOP )) { - filename = tree->filename ; - lineno = tree->lineno ; - } - - /* make sure we resolve the true & false labels for ifx */ - if (tree->type == EX_OP && tree->opval.op == IFX ) { - symbol *csym ; - - if (tree->trueLabel) { - if (( csym = findSym(LabelTab,tree->trueLabel, - tree->trueLabel->name))) - tree->trueLabel = csym ; - else - werror(E_LABEL_UNDEF,tree->trueLabel->name); - } - - if (tree->falseLabel) { - if (( csym = findSym(LabelTab, - tree->falseLabel, - tree->falseLabel->name))) - tree->falseLabel = csym ; - else - werror(E_LABEL_UNDEF,tree->falseLabel->name); - } - - } - - /* if this is a label resolve it from the labelTab*/ - if (IS_AST_VALUE(tree) && - tree->opval.val->sym && - tree->opval.val->sym->islbl) { - - symbol *csym = findSym (LabelTab, tree->opval.val->sym , - tree->opval.val->sym->name); + /* walk the entire tree and check for values */ + /* with symbols if we find one then replace */ + /* symbol with that from the symbol table */ - if (!csym) - werror (E_LABEL_UNDEF,tree->opval.val->sym->name); - else - tree->opval.val->sym = csym ; + if (tree == NULL) + return tree; - goto resolveChildren ; + /* print the line */ + /* if not block & function */ + if (tree->type == EX_OP && + (tree->opval.op != FUNCTION && + tree->opval.op != BLOCK && + tree->opval.op != NULLOP)) + { + filename = tree->filename; + lineno = tree->lineno; } - /* do only for leafs */ - if (IS_AST_VALUE(tree) && - tree->opval.val->sym && - ! tree->opval.val->sym->implicit ) { + /* make sure we resolve the true & false labels for ifx */ + if (tree->type == EX_OP && tree->opval.op == IFX) + { + symbol *csym; - symbol *csym = findSymWithLevel (SymbolTab,tree->opval.val->sym); - - /* if found in the symbol table & they r not the same */ - if (csym && tree->opval.val->sym != csym ) { - tree->opval.val->sym = csym ; - tree->opval.val->type = csym->type; - tree->opval.val->etype = csym->etype; + if (tree->trueLabel) + { + if ((csym = findSym (LabelTab, tree->trueLabel, + tree->trueLabel->name))) + tree->trueLabel = csym; + else + werror (E_LABEL_UNDEF, tree->trueLabel->name); } - - /* if not found in the symbol table */ - /* mark it as undefined assume it is*/ - /* an integer in data space */ - if (!csym && !tree->opval.val->sym->implicit) { - - /* if this is a function name then */ - /* mark it as returning an int */ - if (tree->funcName) { - tree->opval.val->sym->type = newLink(); - DCL_TYPE(tree->opval.val->sym->type) = FUNCTION; - tree->opval.val->sym->type->next = - 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); - } else { - tree->opval.val->sym->undefined =1 ; - tree->opval.val->type = - tree->opval.val->etype = newIntLink(); - tree->opval.val->sym->type = - tree->opval.val->sym->etype = newIntLink(); + + if (tree->falseLabel) + { + if ((csym = findSym (LabelTab, + tree->falseLabel, + tree->falseLabel->name))) + tree->falseLabel = csym; + else + werror (E_LABEL_UNDEF, tree->falseLabel->name); + } + + } + + /* if this is a label resolve it from the labelTab */ + if (IS_AST_VALUE (tree) && + tree->opval.val->sym && + tree->opval.val->sym->islbl) + { + + symbol *csym = findSym (LabelTab, tree->opval.val->sym, + tree->opval.val->sym->name); + + if (!csym) + werror (E_LABEL_UNDEF, tree->opval.val->sym->name); + else + tree->opval.val->sym = csym; + + goto resolveChildren; + } + + /* do only for leafs */ + if (IS_AST_VALUE (tree) && + tree->opval.val->sym && + !tree->opval.val->sym->implicit) + { + + symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym); + + /* if found in the symbol table & they r not the same */ + if (csym && tree->opval.val->sym != csym) + { + tree->opval.val->sym = csym; + tree->opval.val->type = csym->type; + tree->opval.val->etype = csym->etype; + } + + /* if not found in the symbol table */ + /* mark it as undefined assume it is */ + /* an integer in data space */ + if (!csym && !tree->opval.val->sym->implicit) + { + + /* if this is a function name then */ + /* mark it as returning an int */ + if (tree->funcName) + { + tree->opval.val->sym->type = newLink (); + DCL_TYPE (tree->opval.val->sym->type) = FUNCTION; + tree->opval.val->sym->type->next = + 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); + allocVariables (tree->opval.val->sym); } - } - } + else + { + tree->opval.val->sym->undefined = 1; + tree->opval.val->type = + tree->opval.val->etype = newIntLink (); + tree->opval.val->sym->type = + tree->opval.val->sym->etype = newIntLink (); + } + } + } - resolveChildren: - resolveSymbols (tree->left); - resolveSymbols (tree->right); - - return tree; +resolveChildren: + resolveSymbols (tree->left); + resolveSymbols (tree->right); + + return tree; } /*-----------------------------------------------------------------*/ /* setAstLineno - walks a ast tree & sets the line number */ /*-----------------------------------------------------------------*/ -int setAstLineno ( ast *tree, int lineno) +int +setAstLineno (ast * tree, int lineno) { - if (!tree) - return 0; - - tree->lineno = lineno ; - setAstLineno ( tree->left, lineno); - setAstLineno ( tree->right, lineno); + if (!tree) return 0; + + tree->lineno = lineno; + setAstLineno (tree->left, lineno); + setAstLineno (tree->right, lineno); + return 0; } #if 0 @@ -464,946 +505,1124 @@ int setAstLineno ( ast *tree, int lineno) /*-----------------------------------------------------------------*/ /* resolveFromTable - will return the symbal table value */ /*-----------------------------------------------------------------*/ -value *resolveFromTable (value *val) +value * +resolveFromTable (value * val) { - symbol *csym ; + symbol *csym; - if (!val->sym) - return val; + if (!val->sym) + return val; - csym = findSymWithLevel (SymbolTab,val->sym); - - /* if found in the symbol table & they r not the same */ - if (csym && val->sym != csym && - csym->level == val->sym->level && - csym->_isparm && - !csym->ismyparm) { - - val->sym = csym ; - val->type = csym->type; - val->etype = csym->etype; - } + csym = findSymWithLevel (SymbolTab, val->sym); - return val; + /* if found in the symbol table & they r not the same */ + if (csym && val->sym != csym && + csym->level == val->sym->level && + csym->_isparm && + !csym->ismyparm) + { + + val->sym = csym; + val->type = csym->type; + val->etype = csym->etype; + } + + return val; } #endif /*-----------------------------------------------------------------*/ /* funcOfType :- function of type with name */ /*-----------------------------------------------------------------*/ -symbol *funcOfType (char *name, sym_link *type, sym_link *argType, - int nArgs , int rent) +symbol * +funcOfType (char *name, sym_link * type, sym_link * argType, + int nArgs, int rent) { - symbol *sym; - int argStack = 0; - /* create the symbol */ - sym = newSymbol (name,0); - - /* if arguments required */ - if (nArgs) { + symbol *sym; + /* create the symbol */ + sym = newSymbol (name, 0); + + /* setup return value */ + sym->type = newLink (); + DCL_TYPE (sym->type) = FUNCTION; + sym->type->next = copyLinkChain (type); + sym->etype = getSpec (sym->type); + FUNC_ISREENT(sym->type) = rent; + + /* if arguments required */ + if (nArgs) + { + value *args; + args = FUNC_ARGS(sym->type) = newValue (); - value *args ; - args = sym->args = newValue(); + while (nArgs--) + { + args->type = copyLinkChain (argType); + args->etype = getSpec (args->type); + if (!nArgs) + break; + args = args->next = newValue (); + } + } + + /* save it */ + addSymChain (sym); + sym->cdef = 1; + allocVariables (sym); + return sym; - while (nArgs--) { - argStack += getSize(type); - args->type = copyLinkChain(argType); - args->etype = getSpec(args->type); - if (!nArgs) - break; - args = args->next = newValue(); - } - } - - /* setup return value */ - sym->type = newLink(); - DCL_TYPE(sym->type) = FUNCTION; - sym->type->next = copyLinkChain(type); - sym->etype = getSpec(sym->type); - SPEC_RENT(sym->etype) = rent; - - /* save it */ - addSymChain(sym); - sym->cdef = 1; - sym->argStack = (rent ? argStack : 0); - allocVariables (sym); - return sym; - } /*-----------------------------------------------------------------*/ /* reverseParms - will reverse a parameter tree */ /*-----------------------------------------------------------------*/ -void reverseParms (ast *ptree) +void +reverseParms (ast * ptree) { - ast *ttree; - if (!ptree) - return ; + ast *ttree; + if (!ptree) + return; - /* top down if we find a nonParm tree then quit */ - if (ptree->type == EX_OP && ptree->opval.op == PARAM ) { - ttree = ptree->left; - ptree->left = ptree->right; - ptree->right = ttree; - reverseParms(ptree->left); - reverseParms(ptree->right); + /* top down if we find a nonParm tree then quit */ + if (ptree->type == EX_OP && ptree->opval.op == PARAM) + { + ttree = ptree->left; + ptree->left = ptree->right; + ptree->right = ttree; + reverseParms (ptree->left); + reverseParms (ptree->right); } - return ; + return; } /*-----------------------------------------------------------------*/ /* processParms - makes sure the parameters are okay and do some */ /* processing with them */ /*-----------------------------------------------------------------*/ -int processParms (ast *func, value *defParm, - ast *actParm, - int *parmNumber) +int +processParms (ast * func, + value *defParm, + ast * actParm, + int *parmNumber, // unused, although updated + bool rightmost) { - sym_link *fetype = func->etype; + /* if none of them exist */ + if (!defParm && !actParm) + return 0; - /* if none of them exist */ - if ( !defParm && !actParm) - return 0; - - /* 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 && !IS_RENT(fetype) && !options.stackAuto) { - werror (E_NONRENT_ARGS); - return 1; - } - - /* if defined parameters ended but actual parameters */ - /* exist and this is not defined as a variable arg */ - /* also check if statckAuto option is specified */ - if ((! defParm) && actParm && (!func->hasVargs ) && - !options.stackAuto && !IS_RENT(fetype)) { - werror(E_TOO_MANY_PARMS); - return 1; - } - - /* if defined parameters present but no actual parameters */ - if ( defParm && ! actParm) { - werror(E_TO_FEW_PARMS); + 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); + } + + /* 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) + { + werror (W_NONRENT_ARGS); return 1; } - - /* If this is a varargs function... */ - if (!defParm && actParm && func->hasVargs ) + + /* if defined parameters ended but actual parameters */ + /* exist and this is not defined as a variable arg */ + if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype)) { - ast *newType = NULL; - - if (IS_CAST_OP(actParm) - || (IS_AST_LIT_VALUE(actParm) && actParm->values.literalFromCast)) - { - /* Parameter was explicitly typecast; don't touch it. */ - return 0; - } - - /* If it's a small integer, upcast to int. */ - if (IS_INTEGRAL(actParm->ftype) - && getSize(actParm->ftype) < INTSIZE) - { - newType = newAst_LINK(INTTYPE); - } - - if (IS_PTR(actParm->ftype) && !IS_GENPTR(actParm->ftype)) - { - newType = newAst_LINK(copyLinkChain(actParm->ftype)); - DCL_TYPE(newType->opval.lnk) = GPOINTER; - } - - if (IS_AGGREGATE(actParm->ftype)) - { - newType = newAst_LINK(copyLinkChain(actParm->ftype)); - DCL_TYPE(newType->opval.lnk) = GPOINTER; - } - - if (newType) - { - /* cast required; change this op to a cast. */ - 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) || - processParms (func,NULL,actParm->right,parmNumber) ); - } - return 0; - } - - /* if defined parameters ended but actual has not & */ - /* stackAuto */ - if (! defParm && actParm && - (options.stackAuto || IS_RENT(fetype))) - 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->next, actParm->right,parmNumber) ); - } else { - /* if more defined parameters present but no more actual parameters */ - if (defParm->next) { - werror(E_TO_FEW_PARMS); - return 1; + werror (E_TOO_MANY_PARMS); + return 1; + } + + /* if defined parameters present but no actual parameters */ + if (defParm && !actParm) + { + werror (E_TOO_FEW_PARMS); + return 1; + } + + 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)) + { + ast *newType = NULL; + sym_link *ftype; + + if (IS_CAST_OP (actParm) + || (IS_AST_LIT_VALUE (actParm) && actParm->values.literalFromCast)) + { + /* Parameter was explicitly typecast; don't touch it. */ + return 0; + } + + /* The ternary ('?') operator is weird: the ftype of the + * operator is the type of the condition, but it will return a + * (possibly) different type. + */ + if (IS_TERNARY_OP(actParm)) + { + assert(IS_COLON_OP(actParm->right)); + assert(actParm->right->left); + ftype = actParm->right->left->ftype; + } + else + { + ftype = actParm->ftype; } + + /* If it's a small integer, upcast to int. */ + if (IS_INTEGRAL (ftype) + && (getSize (ftype) < (unsigned) INTSIZE)) + { + newType = newAst_LINK(INTTYPE); + } + + if (IS_PTR(ftype) && !IS_GENPTR(ftype)) + { + newType = newAst_LINK (copyLinkChain(ftype)); + DCL_TYPE (newType->opval.lnk) = GPOINTER; + } + + if (IS_AGGREGATE (ftype)) + { + newType = newAst_LINK (copyLinkChain (ftype)); + DCL_TYPE (newType->opval.lnk) = GPOINTER; + } + if (newType) + { + /* cast required; change this op to a cast. */ + ast *parmCopy = decorateType(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)); + } + return 0; } - - /* the parameter type must be atleast castable */ - if (checkType(defParm->type,actParm->ftype) == 0) { - werror(E_TYPE_MISMATCH_PARM,*parmNumber); - werror(E_CONTINUE,"defined type "); - printTypeChain(defParm->type,stderr);fprintf(stderr,"\n"); - werror(E_CONTINUE,"actual type "); - printTypeChain(actParm->ftype,stderr);fprintf(stderr,"\n"); - } - - /* if the parameter is castable then add the cast */ - if ( checkType (defParm->type,actParm->ftype) < 0) { - ast *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->argSym = resolveFromTable(defParm)->sym ; */ - - actParm->argSym = defParm->sym; - /* make a copy and change the regparm type to the defined parm */ - actParm->etype = getSpec(actParm->ftype = copyLinkChain(actParm->ftype)); - SPEC_REGPARM(actParm->etype) = SPEC_REGPARM(defParm->etype); - (*parmNumber)++; + + /* if defined parameters ended but actual has not & */ + /* reentrant */ + if (!defParm && actParm && + (options.stackAuto || IFFUNC_ISREENT (func->ftype))) 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 + { + /* 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; + } + } + + /* 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))); + + /* 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); + } + + /* make a copy and change the regparm type to the defined parm */ + actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype)); + SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype); + (*parmNumber)++; + return 0; } /*-----------------------------------------------------------------*/ /* createIvalType - generates ival for basic types */ /*-----------------------------------------------------------------*/ -ast *createIvalType ( ast *sym,sym_link *type, initList *ilist) +ast * +createIvalType (ast * sym, sym_link * type, initList * ilist) { - ast *iExpr; - - /* if initList is deep */ - if ( ilist->type == INIT_DEEP ) - ilist = ilist->init.deep ; - - iExpr = decorateType(resolveSymbols(list2expr(ilist))); - return decorateType(newNode('=',sym,iExpr)); + ast *iExpr; + + /* if initList is deep */ + if (ilist->type == INIT_DEEP) + ilist = ilist->init.deep; + + iExpr = decorateType (resolveSymbols (list2expr (ilist))); + return decorateType (newNode ('=', sym, iExpr)); } /*-----------------------------------------------------------------*/ /* createIvalStruct - generates initial value for structures */ /*-----------------------------------------------------------------*/ -ast *createIvalStruct (ast *sym,sym_link *type,initList *ilist) +ast * +createIvalStruct (ast * sym, sym_link * type, initList * ilist) { - ast *rast = NULL ; - symbol *sflds ; - initList *iloop ; - - sflds = SPEC_STRUCT(type)->fields ; - if (ilist->type != INIT_DEEP) { - werror(E_INIT_STRUCT,""); - return NULL ; - } - - iloop = ilist->init.deep; - - for ( ; sflds ; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL )) { - ast *lAst ; - - /* if we have come to end */ - if (!iloop) - 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))); + ast *rast = NULL; + ast *lAst; + symbol *sflds; + initList *iloop; + + sflds = SPEC_STRUCT (type)->fields; + if (ilist->type != INIT_DEEP) + { + werror (E_INIT_STRUCT, ""); + return NULL; + } + + iloop = ilist->init.deep; + + for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) + { + /* if we have come to end */ + if (!iloop) + 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))); } - return rast ; + return rast; } /*-----------------------------------------------------------------*/ /* createIvalArray - generates code for array initialization */ /*-----------------------------------------------------------------*/ -ast *createIvalArray (ast *sym, sym_link *type, initList *ilist) +ast * +createIvalArray (ast * sym, sym_link * type, initList * ilist) { - ast *rast = NULL; - initList *iloop ; - int lcnt = 0, size =0 ; - - /* take care of the special case */ - /* array of characters can be init */ - /* by a string */ - if ( IS_CHAR(type->next) ) - if ( (rast = createIvalCharPtr(sym, - type, - decorateType(resolveSymbols(list2expr(ilist)))))) - - return decorateType(resolveSymbols(rast)); - + ast *rast = NULL; + initList *iloop; + int lcnt = 0, size = 0; + literalList *literalL; + + /* take care of the special case */ + /* array of characters can be init */ + /* by a string */ + if (IS_CHAR (type->next)) + if ((rast = createIvalCharPtr (sym, + type, + decorateType (resolveSymbols (list2expr (ilist)))))) + + return decorateType (resolveSymbols (rast)); + /* not the special case */ - if (ilist->type != INIT_DEEP) { - werror(E_INIT_STRUCT,""); + if (ilist->type != INIT_DEEP) + { + werror (E_INIT_STRUCT, ""); return NULL; } - - iloop = ilist->init.deep ; - lcnt = DCL_ELEM(type); - - for (;;) { - ast *aSym ; - size++ ; - - aSym = newNode('[',sym,newAst_VALUE(valueFromLit(size-1))); - aSym = decorateType(resolveSymbols(aSym)); - rast = createIval (aSym,type->next,iloop,rast) ; - iloop = (iloop ? iloop->next : NULL) ; - if (!iloop) - break; - /* if not array limits given & we */ - /* are out of initialisers then */ - if (!DCL_ELEM(type) && !iloop) - break ; + + iloop = ilist->init.deep; + lcnt = DCL_ELEM (type); + + if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL)) + { + ast *aSym; + + aSym = decorateType (resolveSymbols(sym)); + + rast = newNode(ARRAYINIT, aSym, NULL); + rast->values.constlist = literalL; + + // Make sure size is set to length of initializer list. + while (iloop) + { + size++; + iloop = iloop->next; + } - /* no of elements given and we */ - /* have generated for all of them */ - if (!--lcnt) - break ; + if (lcnt && size > lcnt) + { + // 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; + + werror (W_EXESS_ARRAY_INITIALIZERS, name, lineno); + } + } + else + { + for (;;) + { + ast *aSym; + + aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); + aSym = decorateType (resolveSymbols (aSym)); + rast = createIval (aSym, type->next, iloop, rast); + iloop = (iloop ? iloop->next : NULL); + if (!iloop) + { + break; + } + + /* no of elements given and we */ + /* have generated for all of them */ + if (!--lcnt) + { + // there has to be a better way + char *name=sym->opval.val->sym->name; + int lineno=sym->opval.val->sym->lineDef; + werror (W_EXESS_ARRAY_INITIALIZERS, name, lineno); + + break; + } + } } - + /* if we have not been given a size */ - if (!DCL_ELEM(type)) - DCL_ELEM(type) = size; - - return decorateType(resolveSymbols(rast)); + if (!DCL_ELEM (type)) + { + DCL_ELEM (type) = size; + } + + return decorateType (resolveSymbols (rast)); } /*-----------------------------------------------------------------*/ /* createIvalCharPtr - generates initial values for char pointers */ /*-----------------------------------------------------------------*/ -ast *createIvalCharPtr (ast *sym, sym_link *type, ast *iexpr) -{ - ast *rast = NULL ; - - /* if this is a pointer & right is a literal array then */ - /* just assignment will do */ - if ( IS_PTR(type) && (( IS_LITERAL(iexpr->etype) || - SPEC_SCLS(iexpr->etype) == S_CODE ) - && IS_ARRAY(iexpr->ftype))) - return newNode('=',sym,iexpr); - - /* left side is an array so we have to assign each */ - /* element */ - if (( IS_LITERAL(iexpr->etype) || - SPEC_SCLS(iexpr->etype) == S_CODE ) - && IS_ARRAY(iexpr->ftype)) { - - /* for each character generate an assignment */ - /* to the array element */ - char *s = SPEC_CVAL(iexpr->etype).v_char ; - int i = 0 ; - - while (*s) { - rast = newNode(NULLOP, - rast, - newNode('=', - newNode('[', sym, - newAst_VALUE(valueFromLit(i))), - newAst_VALUE(valueFromLit(*s)))); - i++; - s++; - } - rast = newNode(NULLOP, - rast, - newNode('=', - newNode('[', sym, - newAst_VALUE(valueFromLit(i))), - newAst_VALUE(valueFromLit(*s)))); - return decorateType(resolveSymbols(rast)); - } - - return NULL ; +ast * +createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) +{ + ast *rast = NULL; + + /* if this is a pointer & right is a literal array then */ + /* just assignment will do */ + if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) || + SPEC_SCLS (iexpr->etype) == S_CODE) + && IS_ARRAY (iexpr->ftype))) + return newNode ('=', sym, iexpr); + + /* left side is an array so we have to assign each */ + /* element */ + if ((IS_LITERAL (iexpr->etype) || + SPEC_SCLS (iexpr->etype) == S_CODE) + && IS_ARRAY (iexpr->ftype)) + { + /* for each character generate an assignment */ + /* to the array element */ + char *s = SPEC_CVAL (iexpr->etype).v_char; + int i = 0; + + while (*s) + { + rast = newNode (NULLOP, + rast, + newNode ('=', + newNode ('[', sym, + newAst_VALUE (valueFromLit ((float) i))), + newAst_VALUE (valueFromLit (*s)))); + i++; + s++; + } + rast = newNode (NULLOP, + rast, + newNode ('=', + newNode ('[', sym, + newAst_VALUE (valueFromLit ((float) i))), + newAst_VALUE (valueFromLit (*s)))); + return decorateType (resolveSymbols (rast)); + } + + return NULL; } /*-----------------------------------------------------------------*/ /* createIvalPtr - generates initial value for pointers */ /*-----------------------------------------------------------------*/ -ast *createIvalPtr (ast *sym,sym_link *type,initList *ilist) -{ - ast *rast; - ast *iexpr ; +ast * +createIvalPtr (ast * sym, sym_link * type, initList * ilist) +{ + ast *rast; + ast *iexpr; + + /* if deep then */ + if (ilist->type == INIT_DEEP) + ilist = ilist->init.deep; - /* if deep then */ - if ( ilist->type == INIT_DEEP ) - ilist = ilist->init.deep ; - - iexpr = decorateType(resolveSymbols(list2expr(ilist))); + iexpr = decorateType (resolveSymbols (list2expr (ilist))); - /* if character pointer */ - if (IS_CHAR(type->next)) - if ((rast = createIvalCharPtr (sym,type,iexpr))) - return rast; + /* if character pointer */ + if (IS_CHAR (type->next)) + if ((rast = createIvalCharPtr (sym, type, iexpr))) + return rast; - return newNode('=',sym,iexpr); + return newNode ('=', sym, iexpr); } /*-----------------------------------------------------------------*/ /* createIval - generates code for initial value */ /*-----------------------------------------------------------------*/ -ast *createIval (ast *sym, sym_link *type, initList *ilist, ast *wid) +ast * +createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) { - ast *rast = NULL; - - if (!ilist) - return NULL ; - - /* if structure then */ - if (IS_STRUCT(type)) - rast = createIvalStruct(sym, type,ilist); - else - /* if this is a pointer */ - if (IS_PTR(type)) - rast = createIvalPtr(sym, type,ilist); - else - /* if this is an array */ - if (IS_ARRAY(type)) - rast = createIvalArray(sym, type,ilist); - else - /* if type is SPECIFIER */ - if (IS_SPEC(type)) - rast = createIvalType (sym,type,ilist); - if ( wid ) - return decorateType(resolveSymbols(newNode(NULLOP,wid,rast))); - else - return decorateType(resolveSymbols(rast)) ; + ast *rast = NULL; + + if (!ilist) + return NULL; + + /* if structure then */ + if (IS_STRUCT (type)) + rast = createIvalStruct (sym, type, ilist); + else + /* if this is a pointer */ + if (IS_PTR (type)) + rast = createIvalPtr (sym, type, ilist); + else + /* if this is an array */ + if (IS_ARRAY (type)) + rast = createIvalArray (sym, type, ilist); + else + /* if type is SPECIFIER */ + if (IS_SPEC (type)) + rast = createIvalType (sym, type, ilist); + + if (wid) + return decorateType (resolveSymbols (newNode (NULLOP, wid, rast))); + else + return decorateType (resolveSymbols (rast)); } /*-----------------------------------------------------------------*/ /* initAggregates - initialises aggregate variables with initv */ /*-----------------------------------------------------------------*/ -ast *initAggregates ( symbol *sym, initList *ival, ast *wid) -{ - return createIval (newAst_VALUE(symbolVal(sym)),sym->type,ival,wid); + +/* this has to go */ void printIval (symbol *, sym_link *, initList *, FILE *); + +ast * initAggregates (symbol * sym, initList * ival, ast * wid) { + ast *ast; + symbol *newSym; + + if (getenv("TRY_THE_NEW_INITIALIZER")) { + + if (!TARGET_IS_MCS51 || !(options.model==MODEL_LARGE)) { + fprintf (stderr, "Can't \"TRY_THE_NEW_INITIALIZER\" unless " + "with -mmcs51 and --model-large\n"); + exit(404); + } + + if (SPEC_OCLS(sym->etype)==xdata && + getSize(sym->type) > 16) { // else it isn't worth it: do it the old way + + // copy this symbol + newSym=copySymbol (sym); + SPEC_OCLS(newSym->etype)=code; + sprintf (newSym->name, "%s_init__", sym->name); + sprintf (newSym->rname,"%s_init__", sym->rname); + addSym (SymbolTab, newSym, newSym->name, 0, 0, 1); + + // emit it in the static segment + addSet(&statsg->syms, newSym); + + // now memcpy() the entire array from cseg + ast=newNode (ARRAYINIT, // ASSIGN_AGGREGATE + newAst_VALUE (symbolVal (sym)), + newAst_VALUE (symbolVal (newSym))); + return decorateType(resolveSymbols(ast)); + } + } + + return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid); } /*-----------------------------------------------------------------*/ -/* gatherAutoInit - creates assignment expressions for initial */ -/* values */ +/* gatherAutoInit - creates assignment expressions for initial */ +/* values */ /*-----------------------------------------------------------------*/ -ast *gatherAutoInit ( symbol *autoChain ) +ast * +gatherAutoInit (symbol * autoChain) { - ast *init = NULL ; - ast *work ; - symbol *sym; - - inInitMode =1; - for ( sym = autoChain ; sym ; sym = sym->next ) { - - /* resolve the symbols in the ival */ - if (sym->ival) - resolveIvalSym(sym->ival); - - /* if this is a static variable & has an */ - /* initial value the code needs to be lifted */ - /* here to the main portion since they can be */ - /* initialised only once at the start */ - if ( IS_STATIC(sym->etype) && sym->ival && - SPEC_SCLS(sym->etype) != S_CODE) { - symbol *newSym ; - - /* insert the symbol into the symbol table */ - /* with level = 0 & name = rname */ - newSym = copySymbol (sym); - addSym (SymbolTab,newSym,newSym->name,0,0); - - /* now lift the code to main */ - if (IS_AGGREGATE(sym->type)) - work = initAggregates (sym, sym->ival,NULL); - else - work = newNode('=' ,newAst_VALUE(symbolVal(newSym)), - list2expr(sym->ival)); - - setAstLineno(work,sym->lineDef); + ast *init = NULL; + ast *work; + symbol *sym; - sym->ival = NULL ; - if ( staticAutos ) - staticAutos = newNode(NULLOP,staticAutos,work); - else - staticAutos = work ; - - continue; + inInitMode = 1; + for (sym = autoChain; sym; sym = sym->next) + { + + /* resolve the symbols in the ival */ + if (sym->ival) + resolveIvalSym (sym->ival); + + /* if this is a static variable & has an */ + /* initial value the code needs to be lifted */ + /* here to the main portion since they can be */ + /* initialised only once at the start */ + if (IS_STATIC (sym->etype) && sym->ival && + SPEC_SCLS (sym->etype) != S_CODE) + { + symbol *newSym; + + // this can only be a constant + if (!inInitMode && !IS_LITERAL(sym->ival->init.node->etype)) { + werror (E_CONST_EXPECTED); + } + + /* insert the symbol into the symbol table */ + /* with level = 0 & name = rname */ + newSym = copySymbol (sym); + addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1); + + /* now lift the code to main */ + if (IS_AGGREGATE (sym->type)) + work = initAggregates (sym, sym->ival, NULL); + else + work = newNode ('=', newAst_VALUE (symbolVal (newSym)), + list2expr (sym->ival)); + + setAstLineno (work, sym->lineDef); + + sym->ival = NULL; + if (staticAutos) + staticAutos = newNode (NULLOP, staticAutos, work); + else + staticAutos = work; + + continue; } - - /* if there is an initial value */ - if ( sym->ival && SPEC_SCLS(sym->etype)!=S_CODE) { - if (IS_AGGREGATE(sym->type)) - work = initAggregates (sym,sym->ival,NULL); - else - work = newNode('=' ,newAst_VALUE(symbolVal(sym)), - list2expr(sym->ival)); - - setAstLineno (work,sym->lineDef); - sym->ival = NULL ; - if ( init ) - init = newNode(NULLOP,init,work); - else - init = work ; + + /* if there is an initial value */ + if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE) + { + if (IS_AGGREGATE (sym->type)) + work = initAggregates (sym, sym->ival, NULL); + else + work = newNode ('=', newAst_VALUE (symbolVal (sym)), + list2expr (sym->ival)); + + setAstLineno (work, sym->lineDef); + sym->ival = NULL; + if (init) + init = newNode (NULLOP, init, work); + else + init = work; } } - inInitMode = 0; - return init ; + inInitMode = 0; + return init; } /*-----------------------------------------------------------------*/ /* stringToSymbol - creates a symbol from a literal string */ /*-----------------------------------------------------------------*/ -static value *stringToSymbol (value *val) +static value * +stringToSymbol (value * val) { - char name[SDCC_NAME_MAX+1]; - static int charLbl = 0; - symbol *sym ; - - sprintf(name,"_str_%d",charLbl++); - sym = newSymbol(name,0); /* make it @ level 0 */ - strcpy(sym->rname,name); - - /* copy the type from the value passed */ - sym->type = copyLinkChain(val->type); - sym->etype = getSpec(sym->type); - /* change to storage class & output class */ - SPEC_SCLS(sym->etype) = S_CODE ; - SPEC_CVAL(sym->etype).v_char = SPEC_CVAL(val->etype).v_char ; - SPEC_STAT(sym->etype) = 1; - /* make the level & block = 0 */ - sym->block = sym->level = 0; - sym->isstrlit = 1; - /* create an ival */ - sym->ival = newiList(INIT_NODE,newAst_VALUE(val)); - if (noAlloc == 0) { - /* allocate it */ - addSymChain(sym); - allocVariables(sym); - } - sym->ival = NULL; - return symbolVal(sym); - -} - + char name[SDCC_NAME_MAX + 1]; + static int charLbl = 0; + symbol *sym; + + sprintf (name, "_str_%d", charLbl++); + sym = newSymbol (name, 0); /* make it @ level 0 */ + strcpy (sym->rname, name); + + /* copy the type from the value passed */ + sym->type = copyLinkChain (val->type); + sym->etype = getSpec (sym->type); + /* change to storage class & output class */ + SPEC_SCLS (sym->etype) = S_CODE; + SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char; + SPEC_STAT (sym->etype) = 1; + /* make the level & block = 0 */ + sym->block = sym->level = 0; + sym->isstrlit = 1; + /* create an ival */ + sym->ival = newiList (INIT_NODE, newAst_VALUE (val)); + if (noAlloc == 0) + { + /* allocate it */ + addSymChain (sym); + allocVariables (sym); + } + sym->ival = NULL; + return symbolVal (sym); + +} + /*-----------------------------------------------------------------*/ /* processBlockVars - will go thru the ast looking for block if */ /* a block is found then will allocate the syms */ /* will also gather the auto inits present */ /*-----------------------------------------------------------------*/ -ast *processBlockVars ( ast *tree , int *stack, int action) +ast * +processBlockVars (ast * tree, int *stack, int action) { - if (! tree) - return NULL ; - - /* if this is a block */ - if (tree->type == EX_OP && tree->opval.op == BLOCK ) { - ast *autoInit ; - - if (action == ALLOCATE) { - autoInit = gatherAutoInit (tree->values.sym); - *stack += allocVariables (tree->values.sym); - - /* if there are auto inits then do them */ - if (autoInit) - tree->left = newNode(NULLOP,autoInit,tree->left); - } else /* action is deallocate */ - deallocLocal (tree->values.sym) ; - } - - processBlockVars (tree->left, stack, action); - processBlockVars (tree->right, stack, action); - return tree ; + if (!tree) + return NULL; + + /* if this is a block */ + if (tree->type == EX_OP && tree->opval.op == BLOCK) + { + ast *autoInit; + + if (action == ALLOCATE) + { + *stack += allocVariables (tree->values.sym); + autoInit = gatherAutoInit (tree->values.sym); + + /* if there are auto inits then do them */ + if (autoInit) + tree->left = newNode (NULLOP, autoInit, tree->left); + } + else /* action is deallocate */ + deallocLocal (tree->values.sym); + } + + processBlockVars (tree->left, stack, action); + processBlockVars (tree->right, stack, action); + return tree; } /*-----------------------------------------------------------------*/ /* constExprValue - returns the value of a constant expression */ +/* or NULL if it is not a constant expression */ /*-----------------------------------------------------------------*/ -value *constExprValue (ast *cexpr, int check) +value * +constExprValue (ast * cexpr, int check) { - cexpr = decorateType(resolveSymbols(cexpr)); - - /* if this is not a constant then */ - if (!IS_LITERAL(cexpr->ftype)) { - /* then check if this is a literal array - in code segment */ - if (SPEC_SCLS(cexpr->etype) == S_CODE && - SPEC_CVAL(cexpr->etype).v_char && - IS_ARRAY(cexpr->ftype)) { - value *val = valFromType(cexpr->ftype); - SPEC_SCLS(val->etype) = S_LITERAL; - val->sym =cexpr->opval.val->sym ; - val->sym->type = copyLinkChain(cexpr->ftype); - val->sym->etype = getSpec(val->sym->type); - strcpy(val->name,cexpr->opval.val->sym->rname); - return val; + cexpr = decorateType (resolveSymbols (cexpr)); + + /* if this is not a constant then */ + if (!IS_LITERAL (cexpr->ftype)) + { + /* then check if this is a literal array + in code segment */ + if (SPEC_SCLS (cexpr->etype) == S_CODE && + SPEC_CVAL (cexpr->etype).v_char && + IS_ARRAY (cexpr->ftype)) + { + value *val = valFromType (cexpr->ftype); + SPEC_SCLS (val->etype) = S_LITERAL; + val->sym = cexpr->opval.val->sym; + val->sym->type = copyLinkChain (cexpr->ftype); + val->sym->etype = getSpec (val->sym->type); + strcpy (val->name, cexpr->opval.val->sym->rname); + return val; } - - /* if we are casting a literal value then */ - if (IS_AST_OP(cexpr) && - cexpr->opval.op == CAST && - IS_LITERAL(cexpr->left->ftype)) - return valCastLiteral(cexpr->ftype, - floatFromVal(cexpr->left->opval.val)); - - if (IS_AST_VALUE(cexpr)) - return cexpr->opval.val; - - if (check) - werror(E_CONST_EXPECTED,"found expression"); - return NULL ; + /* if we are casting a literal value then */ + if (IS_AST_OP (cexpr) && + cexpr->opval.op == CAST && + IS_LITERAL (cexpr->left->ftype)) + return valCastLiteral (cexpr->ftype, + floatFromVal (cexpr->left->opval.val)); + + if (IS_AST_VALUE (cexpr)) + return cexpr->opval.val; + + if (check) + werror (E_CONST_EXPECTED, "found expression"); + + return NULL; } - - /* return the value */ - return cexpr->opval.val ; - + + /* return the value */ + return cexpr->opval.val; + } /*-----------------------------------------------------------------*/ /* isLabelInAst - will return true if a given label is found */ /*-----------------------------------------------------------------*/ -bool isLabelInAst (symbol *label, ast *tree) +bool +isLabelInAst (symbol * label, ast * tree) { - if (!tree || IS_AST_VALUE(tree) || IS_AST_LINK(tree)) - return FALSE ; + if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree)) + return FALSE; - if (IS_AST_OP(tree) && - tree->opval.op == LABEL && - isSymbolEqual(AST_SYMBOL(tree->left),label)) - return TRUE; + if (IS_AST_OP (tree) && + tree->opval.op == LABEL && + isSymbolEqual (AST_SYMBOL (tree->left), label)) + return TRUE; + + return isLabelInAst (label, tree->right) && + isLabelInAst (label, tree->left); - return isLabelInAst(label,tree->right) && - isLabelInAst(label,tree->left); - } /*-----------------------------------------------------------------*/ /* isLoopCountable - return true if the loop count can be determi- */ /* -ned at compile time . */ /*-----------------------------------------------------------------*/ -bool isLoopCountable (ast *initExpr, ast *condExpr, ast *loopExpr, - symbol **sym,ast **init, ast **end) +bool +isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr, + symbol ** sym, ast ** init, ast ** end) { - - /* the loop is considered countable if the following - conditions are true :- - - a) initExpr :- = - b) condExpr :- < - c) loopExpr :- ++ - */ - - /* first check the initExpr */ - if ( IS_AST_OP(initExpr) && - initExpr->opval.op == '=' && /* is assignment */ - IS_AST_SYM_VALUE(initExpr->left)) { /* left is a symbol */ - - *sym = AST_SYMBOL(initExpr->left); - *init= initExpr->right; + + /* the loop is considered countable if the following + conditions are true :- + + a) initExpr :- = + b) condExpr :- < + c) loopExpr :- ++ + */ + + /* first check the initExpr */ + if (IS_AST_OP (initExpr) && + initExpr->opval.op == '=' && /* is assignment */ + IS_AST_SYM_VALUE (initExpr->left)) + { /* left is a symbol */ + + *sym = AST_SYMBOL (initExpr->left); + *init = initExpr->right; } - else - return FALSE; - - /* for now the symbol has to be of - integral type */ - if (!IS_INTEGRAL((*sym)->type)) - return FALSE; + else + return FALSE; + + /* for now the symbol has to be of + integral type */ + if (!IS_INTEGRAL ((*sym)->type)) + return FALSE; - /* now check condExpr */ - if (IS_AST_OP(condExpr)) { + /* now check condExpr */ + if (IS_AST_OP (condExpr)) + { - switch (condExpr->opval.op) { + switch (condExpr->opval.op) + { case '<': - if (IS_AST_SYM_VALUE(condExpr->left) && - isSymbolEqual (*sym,AST_SYMBOL(condExpr->left)) && - IS_AST_LIT_VALUE(condExpr->right)) { - *end = condExpr->right; - break; + if (IS_AST_SYM_VALUE (condExpr->left) && + isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) && + IS_AST_LIT_VALUE (condExpr->right)) + { + *end = condExpr->right; + break; } - return FALSE; - + return FALSE; + case '!': - if (IS_AST_OP(condExpr->left) && - condExpr->left->opval.op == '>' && - IS_AST_LIT_VALUE(condExpr->left->right) && - IS_AST_SYM_VALUE(condExpr->left->left)&& - isSymbolEqual (*sym,AST_SYMBOL(condExpr->left->left))) { - - *end = newNode('+', condExpr->left->right, - newAst_VALUE(constVal("1"))); - break; + if (IS_AST_OP (condExpr->left) && + condExpr->left->opval.op == '>' && + IS_AST_LIT_VALUE (condExpr->left->right) && + IS_AST_SYM_VALUE (condExpr->left->left) && + isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left))) + { + + *end = newNode ('+', condExpr->left->right, + newAst_VALUE (constVal ("1"))); + break; } - return FALSE ; - + return FALSE; + default: - return FALSE ; - } - - } + return FALSE; + } - /* check loop expression is of the form ++ */ - if (!IS_AST_OP(loopExpr)) - return FALSE ; + } - /* check if ++ */ - if (loopExpr->opval.op == INC_OP) { - - if (loopExpr->left) { - /* pre */ - if (IS_AST_SYM_VALUE(loopExpr->left) && - isSymbolEqual(*sym,AST_SYMBOL(loopExpr->left))) - return TRUE ; - - } else { - /* post */ - if (IS_AST_SYM_VALUE(loopExpr->right) && - isSymbolEqual(*sym,AST_SYMBOL(loopExpr->right))) - return TRUE ; - } - - } - else { - /* check for += */ - if ( loopExpr->opval.op == ADD_ASSIGN ) { - - if (IS_AST_SYM_VALUE(loopExpr->left) && - isSymbolEqual(*sym,AST_SYMBOL(loopExpr->left)) && - IS_AST_LIT_VALUE(loopExpr->right) && - (int)AST_LIT_VALUE(loopExpr->right) != 1) - return TRUE ; - } - } - + /* check loop expression is of the form ++ */ + if (!IS_AST_OP (loopExpr)) return FALSE; + + /* check if ++ */ + if (loopExpr->opval.op == INC_OP) + { + + if (loopExpr->left) + { + /* pre */ + if (IS_AST_SYM_VALUE (loopExpr->left) && + isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left))) + return TRUE; + + } + else + { + /* post */ + if (IS_AST_SYM_VALUE (loopExpr->right) && + isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right))) + return TRUE; + } + + } + else + { + /* check for += */ + if (loopExpr->opval.op == ADD_ASSIGN) + { + + if (IS_AST_SYM_VALUE (loopExpr->left) && + isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) && + IS_AST_LIT_VALUE (loopExpr->right) && + (int) AST_LIT_VALUE (loopExpr->right) != 1) + return TRUE; + } + } + + return FALSE; } /*-----------------------------------------------------------------*/ /* astHasVolatile - returns true if ast contains any volatile */ /*-----------------------------------------------------------------*/ -bool astHasVolatile (ast *tree) +bool +astHasVolatile (ast * tree) { - if (!tree) - return FALSE ; + if (!tree) + return FALSE; - if (TETYPE(tree) && IS_VOLATILE(TETYPE(tree))) - return TRUE; + if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree))) + return TRUE; - if (IS_AST_OP(tree)) - return astHasVolatile(tree->left) || - astHasVolatile(tree->right); - else - return FALSE ; + if (IS_AST_OP (tree)) + return astHasVolatile (tree->left) || + astHasVolatile (tree->right); + else + return FALSE; } /*-----------------------------------------------------------------*/ -/* astHasPointer - return true if the ast contains any ptr variable*/ +/* astHasPointer - return true if the ast contains any ptr variable */ /*-----------------------------------------------------------------*/ -bool astHasPointer (ast *tree) +bool +astHasPointer (ast * tree) { - if (!tree) - return FALSE ; + if (!tree) + return FALSE; - if (IS_AST_LINK(tree)) - return TRUE; + if (IS_AST_LINK (tree)) + return TRUE; - /* if we hit an array expression then check - only the left side */ - if (IS_AST_OP(tree) && tree->opval.op == '[') - return astHasPointer(tree->left); + /* if we hit an array expression then check + only the left side */ + if (IS_AST_OP (tree) && tree->opval.op == '[') + return astHasPointer (tree->left); - if (IS_AST_VALUE(tree)) - return IS_PTR(tree->ftype) || IS_ARRAY(tree->ftype); + if (IS_AST_VALUE (tree)) + return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype); + + return astHasPointer (tree->left) || + astHasPointer (tree->right); - return astHasPointer(tree->left) || - astHasPointer(tree->right); - } /*-----------------------------------------------------------------*/ /* astHasSymbol - return true if the ast has the given symbol */ /*-----------------------------------------------------------------*/ -bool astHasSymbol (ast *tree, symbol *sym) +bool +astHasSymbol (ast * tree, symbol * sym) { - if (!tree || IS_AST_LINK(tree)) - return FALSE ; + if (!tree || IS_AST_LINK (tree)) + return FALSE; - if (IS_AST_VALUE(tree)) { - if (IS_AST_SYM_VALUE(tree)) - return isSymbolEqual(AST_SYMBOL(tree),sym); - else - return FALSE; + if (IS_AST_VALUE (tree)) + { + if (IS_AST_SYM_VALUE (tree)) + return isSymbolEqual (AST_SYMBOL (tree), sym); + else + return FALSE; } - - return astHasSymbol(tree->left,sym) || - astHasSymbol(tree->right,sym); + + return astHasSymbol (tree->left, sym) || + astHasSymbol (tree->right, sym); +} + +/*-----------------------------------------------------------------*/ +/* astHasDeref - return true if the ast has an indirect access */ +/*-----------------------------------------------------------------*/ +static bool +astHasDeref (ast * tree) +{ + if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree)) + return FALSE; + + if (tree->opval.op == '*' && tree->right == NULL) return TRUE; + + return astHasDeref (tree->left) || astHasDeref (tree->right); } /*-----------------------------------------------------------------*/ /* isConformingBody - the loop body has to conform to a set of rules */ /* for the loop to be considered reversible read on for rules */ /*-----------------------------------------------------------------*/ -bool isConformingBody (ast *pbody, symbol *sym, ast *body) +bool +isConformingBody (ast * pbody, symbol * sym, ast * body) { - - /* we are going to do a pre-order traversal of the - tree && check for the following conditions. (essentially - a set of very shallow tests ) - a) the sym passed does not participate in - any arithmetic operation - b) There are no function calls - c) all jumps are within the body - d) address of loop control variable not taken - e) if an assignment has a pointer on the - left hand side make sure right does not have - loop control variable */ - - /* if we reach the end or a leaf then true */ - if (!pbody || IS_AST_LINK(pbody) || IS_AST_VALUE(pbody)) - return TRUE ; - - - /* if anything else is "volatile" */ - if (IS_VOLATILE(TETYPE(pbody))) - return FALSE; - /* we will walk the body in a pre-order traversal for - efficiency sake */ - switch (pbody->opval.op) { - /*------------------------------------------------------------------*/ - case '[' : - return isConformingBody (pbody->right,sym,body); + /* we are going to do a pre-order traversal of the + tree && check for the following conditions. (essentially + a set of very shallow tests ) + a) the sym passed does not participate in + any arithmetic operation + b) There are no function calls + c) all jumps are within the body + d) address of loop control variable not taken + e) if an assignment has a pointer on the + left hand side make sure right does not have + loop control variable */ + + /* if we reach the end or a leaf then true */ + if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody)) + return TRUE; + + + /* if anything else is "volatile" */ + if (IS_VOLATILE (TETYPE (pbody))) + return FALSE; - /*------------------------------------------------------------------*/ - case PTR_OP: - case '.' : - return TRUE; + /* we will walk the body in a pre-order traversal for + efficiency sake */ + switch (pbody->opval.op) + { +/*------------------------------------------------------------------*/ + case '[': + return isConformingBody (pbody->right, sym, body); + +/*------------------------------------------------------------------*/ + case PTR_OP: + case '.': + return TRUE; + +/*------------------------------------------------------------------*/ + case INC_OP: /* incerement operator unary so left only */ + case DEC_OP: + + /* sure we are not sym is not modified */ + if (pbody->left && + IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; - /*------------------------------------------------------------------*/ - case INC_OP: /* incerement operator unary so left only */ - case DEC_OP: - - /* sure we are not sym is not modified */ - if (pbody->left && - IS_AST_SYM_VALUE(pbody->left) && - isSymbolEqual(AST_SYMBOL(pbody->left),sym)) - return FALSE; + if (pbody->right && + IS_AST_SYM_VALUE (pbody->right) && + isSymbolEqual (AST_SYMBOL (pbody->right), sym)) + return FALSE; - if (pbody->right && - IS_AST_SYM_VALUE(pbody->right) && - isSymbolEqual(AST_SYMBOL(pbody->right),sym)) - return FALSE; + return TRUE; - return TRUE; +/*------------------------------------------------------------------*/ - /*------------------------------------------------------------------*/ + case '*': /* can be unary : if right is null then unary operation */ + case '+': + case '-': + case '&': - case '*' : /* can be unary : if right is null then unary operation */ - case '+' : - case '-' : - case '&': - - /* if right is NULL then unary operation */ - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* address of */ - /*----------------------------*/ - if ( ! pbody->right ) { - if (IS_AST_SYM_VALUE(pbody->left) && - isSymbolEqual(AST_SYMBOL(pbody->left),sym)) - return FALSE; - else - return isConformingBody(pbody->left,sym,body) ; - } else { - if (astHasSymbol(pbody->left,sym) || - astHasSymbol(pbody->right,sym)) - return FALSE; + /* if right is NULL then unary operation */ +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* address of */ +/*----------------------------*/ + if (!pbody->right) + { + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + else + return isConformingBody (pbody->left, sym, body); + } + else + { + if (astHasSymbol (pbody->left, sym) || + astHasSymbol (pbody->right, sym)) + return FALSE; } - - /*------------------------------------------------------------------*/ - case '|': - case '^': - case '/': - case '%': + +/*------------------------------------------------------------------*/ + case '|': + case '^': + case '/': + case '%': case LEFT_OP: case RIGHT_OP: - - 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); - - case '~' : - case '!' : + 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); + + case '~': + case '!': case RRC: case RLC: case GETHBIT: - if (IS_AST_SYM_VALUE(pbody->left) && - isSymbolEqual(AST_SYMBOL(pbody->left),sym)) - return FALSE; - return isConformingBody (pbody->left,sym,body); - - /*------------------------------------------------------------------*/ + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + return isConformingBody (pbody->left, sym, body); + +/*------------------------------------------------------------------*/ case AND_OP: case OR_OP: - case '>' : - case '<' : + case '>': + case '<': case LE_OP: case GE_OP: case EQ_OP: case NE_OP: - case '?' : - case ':' : - case SIZEOF: /* evaluate wihout code generation */ + case '?': + case ':': + case SIZEOF: /* evaluate wihout code generation */ - return isConformingBody(pbody->left,sym,body) && - isConformingBody(pbody->right,sym,body); + return isConformingBody (pbody->left, sym, body) && + isConformingBody (pbody->right, sym, body); - /*------------------------------------------------------------------*/ - case '=' : - - /* if left has a pointer & right has loop - control variable then we cannot */ - if (astHasPointer(pbody->left) && - astHasSymbol (pbody->right,sym)) - return FALSE ; - if (astHasVolatile(pbody->left)) - return FALSE ; - - if (IS_AST_SYM_VALUE(pbody->left) && - isSymbolEqual(AST_SYMBOL(pbody->left),sym)) - return FALSE ; - - if (astHasVolatile(pbody->left)) - return FALSE; +/*------------------------------------------------------------------*/ + case '=': + + /* if left has a pointer & right has loop + control variable then we cannot */ + if (astHasPointer (pbody->left) && + astHasSymbol (pbody->right, sym)) + return FALSE; + if (astHasVolatile (pbody->left)) + return FALSE; + + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + + if (astHasVolatile (pbody->left)) + return FALSE; + + if (astHasDeref(pbody->right)) return FALSE; - return isConformingBody(pbody->left,sym,body) && - isConformingBody(pbody->right,sym,body); + return isConformingBody (pbody->left, sym, body) && + isConformingBody (pbody->right, sym, body); case MUL_ASSIGN: case DIV_ASSIGN: @@ -1414,47 +1633,47 @@ bool isConformingBody (ast *pbody, symbol *sym, ast *body) case LEFT_ASSIGN: case SUB_ASSIGN: case ADD_ASSIGN: - assert("Parser should not have generated this\n"); - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* comma operator */ - /*----------------------------*/ - case ',' : - return isConformingBody(pbody->left,sym,body) && - isConformingBody(pbody->right,sym,body); - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* function call */ - /*----------------------------*/ + assert ("Parser should not have generated this\n"); + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* comma operator */ +/*----------------------------*/ + case ',': + return isConformingBody (pbody->left, sym, body) && + isConformingBody (pbody->right, sym, body); + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* function call */ +/*----------------------------*/ case CALL: - return FALSE; + return FALSE; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* return statement */ - /*----------------------------*/ +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* return statement */ +/*----------------------------*/ case RETURN: - return FALSE ; + return FALSE; case GOTO: - if (isLabelInAst (AST_SYMBOL(pbody->left),body)) - return TRUE ; - else - return FALSE; + if (isLabelInAst (AST_SYMBOL (pbody->left), body)) + return TRUE; + else + return FALSE; case SWITCH: - if (astHasSymbol(pbody->left,sym)) - return FALSE ; + if (astHasSymbol (pbody->left, sym)) + return FALSE; default: - break; + break; } - return isConformingBody(pbody->left,sym,body) && - isConformingBody(pbody->right,sym,body); - - + return isConformingBody (pbody->left, sym, body) && + isConformingBody (pbody->right, sym, body); + + } @@ -1463,1449 +1682,1569 @@ bool 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 isLoopReversible (ast *loop, symbol **loopCntrl, - ast **init, ast **end ) +bool +isLoopReversible (ast * loop, symbol ** loopCntrl, + ast ** init, ast ** end) { - /* if option says don't do it then don't */ - if (optimize.noLoopReverse) - return 0; - /* there are several tests to determine this */ - - /* for loop has to be of the form - for ( = ; - [ < ] ; - [++] | [ += 1] | [ = + 1] ) - forBody */ - if (! isLoopCountable (AST_FOR(loop,initExpr), - AST_FOR(loop,condExpr), - AST_FOR(loop,loopExpr), - loopCntrl,init,end)) - return 0; + /* if option says don't do it then don't */ + if (optimize.noLoopReverse) + return 0; + /* there are several tests to determine this */ + + /* for loop has to be of the form + for ( = ; + [ < ] ; + [++] | [ += 1] | [ = + 1] ) + forBody */ + if (!isLoopCountable (AST_FOR (loop, initExpr), + AST_FOR (loop, condExpr), + AST_FOR (loop, loopExpr), + loopCntrl, init, end)) + return 0; - /* now do some serious checking on the body of the loop - */ - - return isConformingBody(loop->left,*loopCntrl,loop->left); + /* now do some serious checking on the body of the loop + */ + + return isConformingBody (loop->left, *loopCntrl, loop->left); } /*-----------------------------------------------------------------*/ /* replLoopSym - replace the loop sym by loop sym -1 */ /*-----------------------------------------------------------------*/ -static void replLoopSym ( ast *body, symbol *sym) +static void +replLoopSym (ast * body, symbol * sym) { - /* reached end */ - if (!body || IS_AST_LINK(body)) - return ; + /* reached end */ + if (!body || IS_AST_LINK (body)) + return; - if (IS_AST_SYM_VALUE(body)) { - - if (isSymbolEqual(AST_SYMBOL(body),sym)) { - - body->type = EX_OP; - body->opval.op = '-'; - body->left = newAst_VALUE(symbolVal(sym)); - body->right= newAst_VALUE(constVal("1")); + if (IS_AST_SYM_VALUE (body)) + { + + if (isSymbolEqual (AST_SYMBOL (body), sym)) + { + + body->type = EX_OP; + body->opval.op = '-'; + body->left = newAst_VALUE (symbolVal (sym)); + body->right = newAst_VALUE (constVal ("1")); } - - return; - + + return; + } - - replLoopSym(body->left,sym); - replLoopSym(body->right,sym); - + + replLoopSym (body->left, sym); + replLoopSym (body->right, sym); + } /*-----------------------------------------------------------------*/ /* reverseLoop - do the actual loop reversal */ /*-----------------------------------------------------------------*/ -ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end) -{ - ast *rloop ; - - /* create the following tree - = loopCount ; - for_continue: - forbody - -= 1; - if (sym) goto for_continue ; - = end */ - - /* put it together piece by piece */ - rloop = newNode (NULLOP, - createIf(newAst_VALUE(symbolVal(sym)), - newNode(GOTO, - newAst_VALUE(symbolVal(AST_FOR(loop,continueLabel))), - NULL),NULL), - newNode('=', - newAst_VALUE(symbolVal(sym)), - end)); - - replLoopSym(loop->left, sym); - - rloop = newNode(NULLOP, - newNode('=', - newAst_VALUE(symbolVal(sym)), - newNode('-',end,init)), - createLabel(AST_FOR(loop,continueLabel), - newNode(NULLOP, - loop->left, - newNode(NULLOP, - newNode(SUB_ASSIGN, - newAst_VALUE(symbolVal(sym)), - newAst_VALUE(constVal("1"))), - rloop )))); - - return decorateType(rloop); +ast * +reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) +{ + ast *rloop; + + /* create the following tree + = loopCount ; + for_continue: + forbody + -= 1; + if (sym) goto for_continue ; + = end */ + + /* put it together piece by piece */ + rloop = newNode (NULLOP, + createIf (newAst_VALUE (symbolVal (sym)), + newNode (GOTO, + newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))), + NULL), NULL), + newNode ('=', + newAst_VALUE (symbolVal (sym)), + end)); + + replLoopSym (loop->left, sym); + + rloop = newNode (NULLOP, + newNode ('=', + newAst_VALUE (symbolVal (sym)), + newNode ('-', end, init)), + createLabel (AST_FOR (loop, continueLabel), + newNode (NULLOP, + loop->left, + newNode (NULLOP, + newNode (SUB_ASSIGN, + newAst_VALUE (symbolVal (sym)), + newAst_VALUE (constVal ("1"))), + rloop)))); + + return decorateType (rloop); } -#define DEMAND_INTEGER_PROMOTION +//#define DEMAND_INTEGER_PROMOTION #ifdef DEMAND_INTEGER_PROMOTION /*-----------------------------------------------------------------*/ /* walk a tree looking for the leaves. Add a typecast to the given */ -/* type to each value leaf node. */ +/* type to each value leaf node. */ /*-----------------------------------------------------------------*/ -void pushTypeCastToLeaves(sym_link *type, ast *node, ast **parentPtr) +void +pushTypeCastToLeaves (sym_link * type, ast * node, ast ** parentPtr) { - if (!node) + if (!node || IS_CALLOP(node)) { - /* WTF? We should never get here. */ - return; + /* WTF? We should never get here. */ + return; } - - if (!node->left && !node->right) + + if (!node->left && !node->right) { - /* We're at a leaf; if it's a value, apply the typecast */ - if (node->type == EX_VALUE && IS_INTEGRAL(TTYPE(node))) - { - *parentPtr = decorateType(newNode(CAST, - newAst_LINK(copyLinkChain(type)), - node)); + /* We're at a leaf; if it's a value, apply the typecast */ + if (node->type == EX_VALUE && IS_INTEGRAL (TTYPE (node))) + { + *parentPtr = decorateType (newNode (CAST, + newAst_LINK (copyLinkChain (type)), + node)); } } - else + else { - if (node->left) - { - pushTypeCastToLeaves(type, node->left, &(node->left)); - } - if (node->right) - { - pushTypeCastToLeaves(type, node->right, &(node->right)); - } + if (node->left) + { + pushTypeCastToLeaves (type, node->left, &(node->left)); + } + if (node->right) + { + pushTypeCastToLeaves (type, node->right, &(node->right)); + } } } #endif /*-----------------------------------------------------------------*/ -/* Given an assignment operation in a tree, determine if the LHS */ -/* (the result) has a different (integer) type than the RHS. */ -/* If so, walk the RHS and add a typecast to the type of the LHS */ -/* to all leaf nodes. */ +/* 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 */ /*-----------------------------------------------------------------*/ -void propAsgType(ast *tree) +ast * +decorateType (ast * tree) { -#ifdef DEMAND_INTEGER_PROMOTION - if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) + int parmNumber; + sym_link *p; + + if (!tree) + return tree; + + /* if already has type then do nothing */ + if (tree->decorated) + return tree; + + tree->decorated = 1; + + /* print the line */ + /* if not block & function */ + if (tree->type == EX_OP && + (tree->opval.op != FUNCTION && + tree->opval.op != BLOCK && + tree->opval.op != NULLOP)) { - /* Nothing to do here... */ - return; + filename = tree->filename; + lineno = tree->lineno; } - - if (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) + + /* if any child is an error | this one is an error do nothing */ + if (tree->isError || + (tree->left && tree->left->isError) || + (tree->right && tree->right->isError)) + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* leaf has been reached */ +/*----------------------------*/ + /* if this is of type value */ + /* just get the type */ + if (tree->type == EX_VALUE) { - pushTypeCastToLeaves(LTYPE(tree), tree->right, &(tree->right)); - } -#else - (void)tree; -#endif -} -/*-----------------------------------------------------------------*/ -/* 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 */ -/*-----------------------------------------------------------------*/ -ast *decorateType (ast *tree) -{ - int parmNumber ; - sym_link *p; - - if ( ! tree ) - return tree ; - - /* if already has type then do nothing */ - if ( tree->decorated ) - return tree ; - - tree->decorated = 1; - - /* print the line */ - /* if not block & function */ - if ( tree->type == EX_OP && - ( tree->opval.op != FUNCTION && - tree->opval.op != BLOCK && - tree->opval.op != NULLOP )) { - filename = tree->filename ; - lineno = tree->lineno ; - } - - /* if any child is an error | this one is an error do nothing */ - if ( tree->isError || - ( tree->left && tree->left->isError) || - ( tree->right && tree->right->isError )) - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* leaf has been reached */ - /*----------------------------*/ - /* if this is of type value */ - /* just get the type */ - if ( tree->type == EX_VALUE ) { - - if ( IS_LITERAL(tree->opval.val->etype) ) { - - /* if this is a character array then declare it */ - if (IS_ARRAY(tree->opval.val->type)) - tree->opval.val = stringToSymbol(tree->opval.val); - - /* otherwise just copy the type information */ - COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type); - if (funcInChain(tree->opval.val->type)) { - tree->hasVargs = tree->opval.val->sym->hasVargs; - tree->args = copyValueChain(tree->opval.val->sym->args) ; - } - return tree ; + if (IS_LITERAL (tree->opval.val->etype)) + { + + /* if this is a character array then declare it */ + if (IS_ARRAY (tree->opval.val->type)) + tree->opval.val = stringToSymbol (tree->opval.val); + + /* otherwise just copy the type information */ + COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type); + return tree; } - - if ( tree->opval.val->sym ) { - /* if the undefined flag is set then give error message */ - if (tree->opval.val->sym->undefined ) { - werror(E_ID_UNDEF,tree->opval.val->sym->name) ; - /* assume int */ - TTYPE(tree) = TETYPE(tree) = - tree->opval.val->type = tree->opval.val->sym->type = - tree->opval.val->etype = tree->opval.val->sym->etype = - copyLinkChain(INTTYPE); - } - else { - - /* if impilicit i.e. struct/union member then no type */ - if (tree->opval.val->sym->implicit ) - TTYPE(tree) = TETYPE(tree) = NULL ; - - else { - - /* else copy the type */ - COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type); - - /* and mark it as referenced */ - tree->opval.val->sym->isref = 1; - /* if this is of type function or function pointer */ - if (funcInChain(tree->opval.val->type)) { - tree->hasVargs = tree->opval.val->sym->hasVargs; - tree->args = copyValueChain(tree->opval.val->sym->args) ; - - } - } + + if (tree->opval.val->sym) + { + /* if the undefined flag is set then give error message */ + if (tree->opval.val->sym->undefined) + { + werror (E_ID_UNDEF, tree->opval.val->sym->name); + /* assume int */ + TTYPE (tree) = TETYPE (tree) = + tree->opval.val->type = tree->opval.val->sym->type = + tree->opval.val->etype = tree->opval.val->sym->etype = + copyLinkChain (INTTYPE); + } + else + { + + /* if impilicit i.e. struct/union member then no type */ + if (tree->opval.val->sym->implicit) + TTYPE (tree) = TETYPE (tree) = NULL; + + else + { + + /* else copy the type */ + COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type); + + /* and mark it as referenced */ + tree->opval.val->sym->isref = 1; } + } } - - return tree ; + + return tree; } - - /* if type link for the case of cast */ - if ( tree->type == EX_LINK ) { - COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.lnk); - return tree ; - } - + + /* if type link for the case of cast */ + if (tree->type == EX_LINK) { - ast *dtl, *dtr; - - dtl = decorateType (tree->left); - dtr = decorateType (tree->right); - - /* this is to take care of situations - when the tree gets rewritten */ - if (dtl != tree->left) - tree->left = dtl; - if (dtr != tree->right) - tree->right = dtr; - } - - /* depending on type of operator do */ - - switch (tree->opval.op) { - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* array node */ - /*----------------------------*/ - 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 ; + COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk); + return tree; + } + + { + ast *dtl, *dtr; + + dtl = decorateType (tree->left); + dtr = decorateType (tree->right); + + /* this is to take care of situations + when the tree gets rewritten */ + if (dtl != tree->left) + tree->left = dtl; + if (dtr != tree->right) + tree->right = dtr; + } + + /* depending on type of operator do */ + + switch (tree->opval.op) + { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* array node */ + /*----------------------------*/ + 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)))) { - werror(E_NEED_ARRAY_PTR,"[]"); - goto errorTreeReturn ; - } - - /* check if the type of the idx */ - if (!IS_INTEGRAL(RTYPE(tree))) { - werror(E_IDX_NOT_INT); - goto errorTreeReturn ; + /* first check if this is a array or a pointer */ + if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree)))) + { + werror (E_NEED_ARRAY_PTR, "[]"); + goto errorTreeReturn; } - - /* if the left is an rvalue then error */ - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"array access"); - goto errorTreeReturn ; + + /* check if the type of the idx */ + if (!IS_INTEGRAL (RTYPE (tree))) + { + werror (E_IDX_NOT_INT); + goto errorTreeReturn; } - RRVAL(tree) = 1; - COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)->next); - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* struct/union */ - /*----------------------------*/ - case '.' : - /* if this is not a structure */ - if (!IS_STRUCT(LTYPE(tree))) { - werror(E_STRUCT_UNION,"."); - goto errorTreeReturn ; - } - TTYPE(tree) = structElemType (LTYPE(tree), - (tree->right->type == EX_VALUE ? - tree->right->opval.val : NULL ),&tree->args); - TETYPE(tree) = getSpec(TTYPE(tree)); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* struct/union pointer */ - /*----------------------------*/ - case PTR_OP: - /* if not pointer to a structure */ - if (!IS_PTR(LTYPE(tree))) { - werror(E_PTR_REQD); - goto errorTreeReturn ; + + /* if the left is an rvalue then error */ + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "array access"); + goto errorTreeReturn; } - - if (!IS_STRUCT(LTYPE(tree)->next)) { - werror(E_STRUCT_UNION,"->"); - goto errorTreeReturn ; + 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; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* struct/union */ + /*----------------------------*/ + case '.': + /* if this is not a structure */ + if (!IS_STRUCT (LTYPE (tree))) + { + werror (E_STRUCT_UNION, "."); + goto errorTreeReturn; } - - TTYPE(tree) = structElemType (LTYPE(tree)->next, - (tree->right->type == EX_VALUE ? - tree->right->opval.val : NULL ),&tree->args); - TETYPE(tree) = getSpec(TTYPE(tree)); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* ++/-- operation */ - /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ - case DEC_OP: + TTYPE (tree) = structElemType (LTYPE (tree), + (tree->right->type == EX_VALUE ? + tree->right->opval.val : NULL)); + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* struct/union pointer */ + /*----------------------------*/ + case PTR_OP: + /* if not pointer to a structure */ + if (!IS_PTR (LTYPE (tree))) { - sym_link *ltc = (tree->right ? RTYPE(tree) : LTYPE(tree) ); - COPYTYPE(TTYPE(tree),TETYPE(tree),ltc); - if (!tree->initMode && IS_CONSTANT(TETYPE(tree))) - werror(E_CODE_WRITE,"++/--"); - - if (tree->right) - RLVAL(tree) = 1; - else - LLVAL(tree) = 1; - return tree ; + werror (E_PTR_REQD); + goto errorTreeReturn; } - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* bitwise and */ - /*----------------------------*/ - case '&': /* can be unary */ - /* if right is NULL then unary operation */ - if ( tree->right ) /* not an unary operation */ { - - if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) { - werror(E_BITWISE_OP); - werror(E_CONTINUE,"left & right types are "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,","); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; - } - - /* if they are both literal */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valBitwise (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree)),'&'); - - tree->right = tree->left = NULL; - TETYPE(tree) = tree->opval.val->etype ; - TTYPE(tree) = tree->opval.val->type; - return tree ; + + if (!IS_STRUCT (LTYPE (tree)->next)) + { + werror (E_STRUCT_UNION, "->"); + goto errorTreeReturn; + } + + TTYPE (tree) = structElemType (LTYPE (tree)->next, + (tree->right->type == EX_VALUE ? + tree->right->opval.val : NULL)); + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* ++/-- operation */ +/*----------------------------*/ + case INC_OP: /* incerement operator unary so left only */ + 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))) + werror (E_CODE_WRITE, "++/--"); + + if (tree->right) + RLVAL (tree) = 1; + else + LLVAL (tree) = 1; + return tree; + } + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* bitwise and */ +/*----------------------------*/ + case '&': /* can be unary */ + /* if right is NULL then unary operation */ + if (tree->right) /* not an unary operation */ + { + + if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) + { + werror (E_BITWISE_OP); + werror (W_CONTINUE, "left & right types are "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, ","); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; } - - /* see if this is a GETHBIT operation if yes - then return that */ + + /* if they are both literal */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) { - ast *otree = optimizeGetHbit(tree); - - if (otree != tree) - return decorateType(otree); + tree->type = EX_VALUE; + tree->opval.val = valBitwise (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree)), '&'); + + tree->right = tree->left = NULL; + TETYPE (tree) = tree->opval.val->etype; + TTYPE (tree) = tree->opval.val->type; + return tree; } - - /* if right or left is literal then result of that type*/ - if (IS_LITERAL(RTYPE(tree))) { - - TTYPE(tree) = copyLinkChain(RTYPE(tree)); - TETYPE(tree) = getSpec(TTYPE(tree)); - SPEC_SCLS(TETYPE(tree)) = S_AUTO; + + /* see if this is a GETHBIT operation if yes + then return that */ + { + ast *otree = optimizeGetHbit (tree); + + if (otree != tree) + return decorateType (otree); + } + +#if 0 + // we can't do this because of "(int & 0xff) << 3" + + /* if right or left is literal then result of that type */ + if (IS_LITERAL (RTYPE (tree))) + { + + TTYPE (tree) = copyLinkChain (RTYPE (tree)); + TETYPE (tree) = getSpec (TTYPE (tree)); + SPEC_SCLS (TETYPE (tree)) = S_AUTO; } - else { - if (IS_LITERAL(LTYPE(tree))) { - TTYPE(tree) = copyLinkChain(LTYPE(tree)); - TETYPE(tree) = getSpec(TTYPE(tree)); - SPEC_SCLS(TETYPE(tree)) = S_AUTO; - + else + { + if (IS_LITERAL (LTYPE (tree))) + { + TTYPE (tree) = copyLinkChain (LTYPE (tree)); + TETYPE (tree) = getSpec (TTYPE (tree)); + SPEC_SCLS (TETYPE (tree)) = S_AUTO; + } - else { - TTYPE(tree) = - computeType (LTYPE(tree), RTYPE(tree)); - TETYPE(tree) = getSpec(TTYPE(tree)); + else + { + TTYPE (tree) = + computeType (LTYPE (tree), RTYPE (tree)); + TETYPE (tree) = getSpec (TTYPE (tree)); } } - LRVAL(tree) = RRVAL(tree) = 1; - return tree ; - } - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* address of */ - /*----------------------------*/ - p = newLink(); - p->class = DECLARATOR; - /* if bit field then error */ - if (IS_BITVAR(tree->left->etype)) { - werror (E_ILLEGAL_ADDR,"addrress of bit variable"); - goto errorTreeReturn ; +#else + TTYPE (tree) = + computeType (LTYPE (tree), RTYPE (tree)); + TETYPE (tree) = getSpec (TTYPE (tree)); +#endif + LRVAL (tree) = RRVAL (tree) = 1; + return tree; } - - if (SPEC_SCLS(tree->left->etype)== S_REGISTER ) { - werror (E_ILLEGAL_ADDR,"address of register variable"); - goto errorTreeReturn; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* address of */ +/*----------------------------*/ + p = newLink (); + p->class = DECLARATOR; + /* if bit field then error */ + if (IS_BITVAR (tree->left->etype)) + { + werror (E_ILLEGAL_ADDR, "address of bit variable"); + goto errorTreeReturn; } - - if (IS_FUNC(LTYPE(tree))) { - werror(E_ILLEGAL_ADDR,"address of function"); - goto errorTreeReturn ; + + if (SPEC_SCLS (tree->left->etype) == S_REGISTER) + { + werror (E_ILLEGAL_ADDR, "address of register variable"); + goto errorTreeReturn; } - - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"address of"); - goto errorTreeReturn ; + + if (IS_FUNC (LTYPE (tree))) + { + werror (E_ILLEGAL_ADDR, "address of function"); + goto errorTreeReturn; + } + + if (IS_LITERAL(LTYPE(tree))) + { + werror (E_ILLEGAL_ADDR, "address of literal"); + goto errorTreeReturn; } - if (SPEC_SCLS(tree->left->etype) == S_CODE) { - DCL_TYPE(p) = CPOINTER ; - DCL_PTR_CONST(p) = port->mem.code_ro; + + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "address of"); + goto errorTreeReturn; } - else - if (SPEC_SCLS(tree->left->etype) == S_XDATA) - DCL_TYPE(p) = FPOINTER; - else - if (SPEC_SCLS(tree->left->etype) == S_XSTACK ) - DCL_TYPE(p) = PPOINTER ; - else - if (SPEC_SCLS(tree->left->etype) == S_IDATA) - DCL_TYPE(p) = IPOINTER ; - else - if (SPEC_SCLS(tree->left->etype) == S_EEPROM) - DCL_TYPE(p) = EEPPOINTER ; - else - DCL_TYPE(p) = POINTER ; - - if (IS_AST_SYM_VALUE(tree->left)) { - AST_SYMBOL(tree->left)->addrtaken = 1; - AST_SYMBOL(tree->left)->allocreq = 1; - } - - 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; - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* bitwise or */ - /*----------------------------*/ - case '|': - /* if the rewrite succeeds then don't go any furthur */ + if (SPEC_SCLS (tree->left->etype) == S_CODE) { - ast *wtree = optimizeRRCRLC ( tree ); - if (wtree != tree) - return decorateType(wtree) ; + DCL_TYPE (p) = CPOINTER; + DCL_PTR_CONST (p) = port->mem.code_ro; } - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* bitwise xor */ - /*----------------------------*/ - case '^': - if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) { - werror(E_BITWISE_OP); - werror(E_CONTINUE,"left & right types are "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,","); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; + else if (SPEC_SCLS (tree->left->etype) == S_XDATA) + DCL_TYPE (p) = FPOINTER; + else if (SPEC_SCLS (tree->left->etype) == S_XSTACK) + DCL_TYPE (p) = PPOINTER; + else if (SPEC_SCLS (tree->left->etype) == S_IDATA) + DCL_TYPE (p) = IPOINTER; + else if (SPEC_SCLS (tree->left->etype) == S_EEPROM) + DCL_TYPE (p) = EEPPOINTER; + else + DCL_TYPE (p) = POINTER; + + if (IS_AST_SYM_VALUE (tree->left)) + { + AST_SYMBOL (tree->left)->addrtaken = 1; + AST_SYMBOL (tree->left)->allocreq = 1; } - - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valBitwise (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree)), - tree->opval.op); - tree->right = tree->left = NULL; - TETYPE(tree) = tree->opval.val->etype; - TTYPE(tree) = tree->opval.val->type; - return tree ; - } - LRVAL(tree) = RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* division */ - /*----------------------------*/ - case '/': - if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) { - werror(E_INVALID_OP,"divide"); - goto errorTreeReturn ; - } - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valDiv (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree))); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(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; + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* bitwise or */ +/*----------------------------*/ + case '|': + /* if the rewrite succeeds then don't go any furthur */ + { + ast *wtree = optimizeRRCRLC (tree); + if (wtree != tree) + return decorateType (wtree); + } +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* bitwise xor */ +/*----------------------------*/ + case '^': + if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) + { + werror (E_BITWISE_OP); + werror (W_CONTINUE, "left & right types are "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, ","); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; + } + + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valBitwise (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree)), + tree->opval.op); + tree->right = tree->left = NULL; + TETYPE (tree) = tree->opval.val->etype; + TTYPE (tree) = tree->opval.val->type; + return tree; + } + LRVAL (tree) = RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* division */ +/*----------------------------*/ + case '/': + if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) + { + werror (E_INVALID_OP, "divide"); + goto errorTreeReturn; + } + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valDiv (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree))); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - LRVAL(tree) = RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* modulus */ - /*----------------------------*/ - case '%': - if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) { - werror(E_BITWISE_OP); - werror(E_CONTINUE,"left & right types are "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,","); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; - } - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valMod (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree))); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + LRVAL (tree) = RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* modulus */ +/*----------------------------*/ + case '%': + if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) + { + werror (E_BITWISE_OP); + werror (W_CONTINUE, "left & right types are "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, ","); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; + } + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valMod (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree))); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - LRVAL(tree) = RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* address dereference */ - /*----------------------------*/ - case '*': /* can be unary : if right is null then unary operation */ - if ( ! tree->right ) { - if (!IS_PTR(LTYPE(tree)) && !IS_ARRAY(LTYPE(tree))) { - werror(E_PTR_REQD); - goto errorTreeReturn ; + LRVAL (tree) = RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ +/* address dereference */ +/*----------------------------*/ + case '*': /* can be unary : if right is null then unary operation */ + if (!tree->right) + { + if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree))) + { + werror (E_PTR_REQD); + goto errorTreeReturn; } - - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"pointer deref"); - goto errorTreeReturn ; + + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "pointer deref"); + goto errorTreeReturn; } - TTYPE(tree) = copyLinkChain ((IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) ? - LTYPE(tree)->next : NULL ); - TETYPE(tree) = getSpec(TTYPE(tree)); - tree->args = tree->left->args ; - tree->hasVargs = tree->left->hasVargs ; - SPEC_CONST(TETYPE(tree)) = DCL_PTR_CONST(LTYPE(tree)); - return tree ; + TTYPE (tree) = copyLinkChain ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) ? + LTYPE (tree)->next : NULL); + TETYPE (tree) = getSpec (TTYPE (tree)); + SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); + return tree; } - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* multiplication */ - /*----------------------------*/ - if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) { - werror(E_INVALID_OP,"multiplication"); - goto errorTreeReturn ; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* multiplication */ +/*----------------------------*/ + if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) + { + werror (E_INVALID_OP, "multiplication"); + goto errorTreeReturn; } - - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valMult (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree))); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valMult (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree))); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + 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 left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; } - - LRVAL(tree) = RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* unary '+' operator */ - /*----------------------------*/ - case '+' : - /* if unary plus */ - if ( ! tree->right ) { - if (!IS_INTEGRAL(LTYPE(tree))) { - werror(E_UNARY_OP,'+'); - goto errorTreeReturn ; + + LRVAL (tree) = RRVAL (tree) = 1; + /* 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))) { + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + SPEC_NOUN(TETYPE(tree)) = V_INT; + } else { + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + } + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* unary '+' operator */ +/*----------------------------*/ + case '+': + /* if unary plus */ + if (!tree->right) + { + if (!IS_INTEGRAL (LTYPE (tree))) + { + werror (E_UNARY_OP, '+'); + goto errorTreeReturn; } - - /* if left is a literal then do it */ - if (IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valFromType(LETYPE(tree)); - tree->left = NULL ; - TETYPE(tree) = TTYPE(tree) = tree->opval.val->type; - return tree ; + + /* if left is a literal then do it */ + if (IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valFromType (LETYPE (tree)); + tree->left = NULL; + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + return tree; } - LRVAL(tree) = 1; - COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)); - return tree ; + LRVAL (tree) = 1; + COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); + return tree; } - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* addition */ - /*----------------------------*/ - - /* this is not a unary operation */ - /* if both pointers then problem */ - if ((IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) && - (IS_PTR(RTYPE(tree)) || IS_ARRAY(RTYPE(tree)))) { - werror(E_PTR_PLUS_PTR); - goto errorTreeReturn ; - } - - if (!IS_ARITHMETIC(LTYPE(tree)) && - !IS_PTR(LTYPE(tree)) && !IS_ARRAY(LTYPE(tree))) { - werror(E_PLUS_INVALID,"+"); - goto errorTreeReturn ; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* addition */ +/*----------------------------*/ + + /* this is not a unary operation */ + /* if both pointers then problem */ + if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) && + (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)))) + { + werror (E_PTR_PLUS_PTR); + goto errorTreeReturn; } - - if (!IS_ARITHMETIC(RTYPE(tree)) && - !IS_PTR(RTYPE(tree)) && !IS_ARRAY(RTYPE(tree))) { - werror(E_PLUS_INVALID,"+"); - goto errorTreeReturn; - } - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valPlus (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree))); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + + if (!IS_ARITHMETIC (LTYPE (tree)) && + !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree))) + { + werror (E_PLUS_INVALID, "+"); + goto errorTreeReturn; + } + + if (!IS_ARITHMETIC (RTYPE (tree)) && + !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree))) + { + werror (E_PLUS_INVALID, "+"); + goto errorTreeReturn; + } + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valPlus (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree))); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - - /* if the right is a pointer or left is a literal - xchange left & right */ - if (IS_ARRAY(RTYPE(tree)) || - IS_PTR(RTYPE(tree)) || - IS_LITERAL(LTYPE(tree))) { - ast *tTree = tree->left ; - tree->left = tree->right ; - tree->right= tTree ; - } - - LRVAL(tree) = RRVAL(tree) = 1; - /* if the left is a pointer */ - if (IS_PTR(LTYPE(tree))) - TETYPE(tree) = getSpec(TTYPE(tree) = - LTYPE(tree)); - else - TETYPE(tree) = getSpec(TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* unary '-' */ - /*----------------------------*/ - case '-' : /* can be unary */ - /* if right is null then unary */ - if ( ! tree->right ) { - - if (!IS_ARITHMETIC(LTYPE(tree))) { - werror(E_UNARY_OP,tree->opval.op); - goto errorTreeReturn ; + + /* if the right is a pointer or left is a literal + xchange left & right */ + if (IS_ARRAY (RTYPE (tree)) || + IS_PTR (RTYPE (tree)) || + IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + LRVAL (tree) = RRVAL (tree) = 1; + /* if the left is a pointer */ + if (IS_PTR (LTYPE (tree))) + TETYPE (tree) = getSpec (TTYPE (tree) = + LTYPE (tree)); + else + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* unary '-' */ +/*----------------------------*/ + case '-': /* can be unary */ + /* if right is null then unary */ + if (!tree->right) + { + + if (!IS_ARITHMETIC (LTYPE (tree))) + { + werror (E_UNARY_OP, tree->opval.op); + goto errorTreeReturn; } - - /* if left is a literal then do it */ - if (IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valUnaryPM(valFromType(LETYPE(tree))); - tree->left = NULL ; - TETYPE(tree) = TTYPE(tree) = tree->opval.val->type; - return tree ; + + /* if left is a literal then do it */ + if (IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valUnaryPM (valFromType (LETYPE (tree))); + tree->left = NULL; + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + SPEC_USIGN(TETYPE(tree)) = 0; + return tree; } - LRVAL(tree) = 1; - TTYPE(tree) = LTYPE(tree); - return tree ; + LRVAL (tree) = 1; + TTYPE (tree) = LTYPE (tree); + return tree; } - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* subtraction */ - /*----------------------------*/ - - if (!(IS_PTR(LTYPE(tree)) || - IS_ARRAY(LTYPE(tree)) || - IS_ARITHMETIC(LTYPE(tree)))) { - werror(E_PLUS_INVALID,"-"); - goto errorTreeReturn ; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* subtraction */ +/*----------------------------*/ + + if (!(IS_PTR (LTYPE (tree)) || + IS_ARRAY (LTYPE (tree)) || + IS_ARITHMETIC (LTYPE (tree)))) + { + werror (E_PLUS_INVALID, "-"); + goto errorTreeReturn; } - - if (!(IS_PTR(RTYPE(tree)) || - IS_ARRAY(RTYPE(tree)) || - IS_ARITHMETIC(RTYPE(tree)))) { - werror(E_PLUS_INVALID,"-"); - goto errorTreeReturn ; + + if (!(IS_PTR (RTYPE (tree)) || + IS_ARRAY (RTYPE (tree)) || + IS_ARITHMETIC (RTYPE (tree)))) + { + werror (E_PLUS_INVALID, "-"); + goto errorTreeReturn; } - - if ( (IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) && - ! (IS_PTR(RTYPE(tree)) || IS_ARRAY(RTYPE(tree)) || - IS_INTEGRAL(RTYPE(tree))) ) { - werror(E_PLUS_INVALID,"-"); - goto errorTreeReturn ; - } - - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valMinus (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree))); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + + if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) && + !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) || + IS_INTEGRAL (RTYPE (tree)))) + { + werror (E_PLUS_INVALID, "-"); + goto errorTreeReturn; + } + + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valMinus (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree))); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - - /* if the left & right are equal then zero */ - if (isAstEqual(tree->left,tree->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; - } - - /* if both of them are pointers or arrays then */ - /* the result is going to be an integer */ - if (( IS_ARRAY(LTYPE(tree)) || IS_PTR(LTYPE(tree))) && - ( IS_ARRAY(RTYPE(tree)) || IS_PTR(RTYPE(tree)))) - TETYPE(tree) = TTYPE(tree) = newIntLink(); - else - /* if only the left is a pointer */ - /* then result is a pointer */ - if (IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) - TETYPE(tree) = getSpec(TTYPE(tree) = - LTYPE(tree)); - else - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); - LRVAL(tree) = RRVAL(tree) = 1; - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* compliment */ - /*----------------------------*/ - case '~' : - /* can be only integral type */ - if (!IS_INTEGRAL(LTYPE(tree))) { - werror(E_UNARY_OP,tree->opval.op); - goto errorTreeReturn ; - } - - /* if left is a literal then do it */ - if (IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valComplement(valFromType(LETYPE(tree))); - tree->left = NULL ; - TETYPE(tree) = TTYPE(tree) = tree->opval.val->type; - return tree ; - } - LRVAL(tree) = 1; - COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* not */ - /*----------------------------*/ - case '!' : - /* can be pointer */ - if (!IS_ARITHMETIC(LTYPE(tree)) && - !IS_PTR(LTYPE(tree)) && - !IS_ARRAY(LTYPE(tree))) { - werror(E_UNARY_OP,tree->opval.op); - goto errorTreeReturn ; + + /* if the left & right are equal then zero */ + if (isAstEqual (tree->left, tree->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; } - - /* if left is a literal then do it */ - if (IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valNot(valFromType(LETYPE(tree))); - tree->left = NULL ; - TETYPE(tree) = TTYPE(tree) = tree->opval.val->type; - return tree ; - } - LRVAL(tree) = 1; - TTYPE(tree) = TETYPE(tree) = newCharLink(); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* shift */ - /*----------------------------*/ + + /* if both of them are pointers or arrays then */ + /* the result is going to be an integer */ + if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) && + (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree)))) + TETYPE (tree) = TTYPE (tree) = newIntLink (); + else + /* if only the left is a pointer */ + /* then result is a pointer */ + if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) + TETYPE (tree) = getSpec (TTYPE (tree) = + LTYPE (tree)); + else + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + LRVAL (tree) = RRVAL (tree) = 1; + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* compliment */ +/*----------------------------*/ + case '~': + /* can be only integral type */ + if (!IS_INTEGRAL (LTYPE (tree))) + { + werror (E_UNARY_OP, tree->opval.op); + goto errorTreeReturn; + } + + /* if left is a literal then do it */ + if (IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valComplement (valFromType (LETYPE (tree))); + tree->left = NULL; + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + return tree; + } + LRVAL (tree) = 1; + COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* not */ +/*----------------------------*/ + case '!': + /* can be pointer */ + if (!IS_ARITHMETIC (LTYPE (tree)) && + !IS_PTR (LTYPE (tree)) && + !IS_ARRAY (LTYPE (tree))) + { + werror (E_UNARY_OP, tree->opval.op); + goto errorTreeReturn; + } + + /* if left is a literal then do it */ + if (IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valNot (valFromType (LETYPE (tree))); + tree->left = NULL; + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + return tree; + } + LRVAL (tree) = 1; + TTYPE (tree) = TETYPE (tree) = newCharLink (); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* shift */ +/*----------------------------*/ case RRC: case RLC: - TTYPE(tree) = LTYPE(tree); - TETYPE(tree) = LETYPE(tree); - return tree ; - + TTYPE (tree) = LTYPE (tree); + TETYPE (tree) = LETYPE (tree); + return tree; + case GETHBIT: - TTYPE(tree) = TETYPE(tree) = newCharLink(); - return tree; + TTYPE (tree) = TETYPE (tree) = newCharLink (); + return tree; case LEFT_OP: case RIGHT_OP: - if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(tree->left->etype)) { - werror(E_SHIFT_OP_INVALID); - werror(E_CONTINUE,"left & right types are "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,","); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; - } - - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valShift (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree)), - (tree->opval.op == LEFT_OP ? 1 : 0)); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype)) + { + werror (E_SHIFT_OP_INVALID); + werror (W_CONTINUE, "left & right types are "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, ","); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; + } + + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valShift (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree)), + (tree->opval.op == LEFT_OP ? 1 : 0)); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - 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)) && - ((int)floatFromVal( valFromType(RETYPE(tree)))) >= - (getSize(LTYPE(tree))*8)) { - 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; - } - LRVAL(tree) = RRVAL(tree) = 1; - if (IS_LITERAL(LTYPE(tree)) && !IS_LITERAL(RTYPE(tree))) { - COPYTYPE(TTYPE(tree),TETYPE(tree),RTYPE(tree)); - } else { - COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)); - } - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* casting */ - /*----------------------------*/ - case CAST: /* change the type */ - /* cannot cast to an aggregate type */ - if (IS_AGGREGATE(LTYPE(tree))) { - werror(E_CAST_ILLEGAL); - goto errorTreeReturn ; + return tree; } - - /* if the right is a literal replace the tree */ - if (IS_LITERAL(RETYPE(tree)) && !IS_PTR(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = - valCastLiteral(LTYPE(tree), - floatFromVal(valFromType(RETYPE(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; - } - - TETYPE(tree) = getSpec(TTYPE(tree)); - - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* logical &&, || */ - /*----------------------------*/ + /* 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)) + { + 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; + } + LRVAL (tree) = RRVAL (tree) = 1; + if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree))) + { + COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree)); + } + else + { + COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); + } + return tree; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* casting */ + /*----------------------------*/ + case CAST: /* change the type */ + /* cannot cast to an aggregate type */ + if (IS_AGGREGATE (LTYPE (tree))) + { + werror (E_CAST_ILLEGAL); + goto errorTreeReturn; + } + + /* make sure the type is complete and sane */ + checkTypeSanity(LETYPE(tree), "(cast)"); + +#if 0 + /* if the right is a literal replace the tree */ + if (IS_LITERAL (RETYPE (tree))) { + if (!IS_PTR (LTYPE (tree))) { + tree->type = EX_VALUE; + tree->opval.val = + valCastLiteral (LTYPE (tree), + floatFromVal (valFromType (RETYPE (tree)))); + tree->left = NULL; + tree->right = NULL; + TTYPE (tree) = tree->opval.val->type; + tree->values.literalFromCast = 1; + } 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); + TTYPE(tree) = newLink(); + DCL_TYPE(TTYPE(tree)) = FPOINTER; + TTYPE(tree)->next = rest; + tree->left->opval.lnk = TTYPE(tree); + LRVAL (tree) = 1; + } else { + TTYPE (tree) = LTYPE (tree); + LRVAL (tree) = 1; + } + } else { + TTYPE (tree) = LTYPE (tree); + LRVAL (tree) = 1; + } +#else + /* 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)) { + werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,SPEC_STRUCT(LETYPE(tree))->tag); + } + /* if the right is a literal replace the tree */ + if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree))) { + tree->type = EX_VALUE; + tree->opval.val = + valCastLiteral (LTYPE (tree), + floatFromVal (valFromType (RETYPE (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; + } +#endif + TETYPE (tree) = getSpec (TTYPE (tree)); + + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* logical &&, || */ +/*----------------------------*/ case AND_OP: case OR_OP: - /* each must me arithmetic type or be a pointer */ - if (!IS_PTR(LTYPE(tree)) && - !IS_ARRAY(LTYPE(tree)) && - !IS_INTEGRAL(LTYPE(tree))) { - werror(E_COMPARE_OP); - goto errorTreeReturn ; + /* each must me arithmetic type or be a pointer */ + if (!IS_PTR (LTYPE (tree)) && + !IS_ARRAY (LTYPE (tree)) && + !IS_INTEGRAL (LTYPE (tree))) + { + werror (E_COMPARE_OP); + goto errorTreeReturn; } - - if (!IS_PTR(RTYPE(tree)) && - !IS_ARRAY(RTYPE(tree)) && - !IS_INTEGRAL(RTYPE(tree))) { - werror(E_COMPARE_OP); - goto errorTreeReturn ; - } - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && - IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valLogicAndOr (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree)), - tree->opval.op); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + + if (!IS_PTR (RTYPE (tree)) && + !IS_ARRAY (RTYPE (tree)) && + !IS_INTEGRAL (RTYPE (tree))) + { + werror (E_COMPARE_OP); + goto errorTreeReturn; + } + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && + IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree)), + tree->opval.op); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - LRVAL(tree) = RRVAL(tree) = 1; - TTYPE(tree) = TETYPE(tree) = newCharLink(); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* comparison operators */ - /*----------------------------*/ - case '>' : - case '<' : - case LE_OP : - case GE_OP : - case EQ_OP : - case NE_OP : - { - ast *lt = optimizeCompare(tree); - - if ( tree != lt ) - return lt; - } - - /* if they are pointers they must be castable */ - if ( IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree))) { - if (checkType(LTYPE(tree),RTYPE(tree)) == 0) { - werror(E_COMPARE_OP); - fprintf(stderr,"comparing type "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,"to type "); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; + LRVAL (tree) = RRVAL (tree) = 1; + TTYPE (tree) = TETYPE (tree) = newCharLink (); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* comparison operators */ +/*----------------------------*/ + case '>': + case '<': + case LE_OP: + case GE_OP: + case EQ_OP: + case NE_OP: + { + ast *lt = optimizeCompare (tree); + + if (tree != lt) + return lt; + } + + /* if they are pointers they must be castable */ + if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) + { + if (compareType (LTYPE (tree), RTYPE (tree)) == 0) + { + werror (E_COMPARE_OP); + fprintf (stderr, "comparing type "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, "to type "); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; } - } - /* else they should be promotable to one another */ - else { - if (!( ( IS_PTR(LTYPE(tree)) && IS_LITERAL(RTYPE(tree))) || - ( IS_PTR(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))))) - - if (checkType (LTYPE(tree),RTYPE(tree)) == 0 ) { - werror(E_COMPARE_OP); - fprintf(stderr,"comparing type "); - printTypeChain(LTYPE(tree),stderr); - fprintf(stderr,"to type "); - printTypeChain(RTYPE(tree),stderr); - fprintf(stderr,"\n"); - goto errorTreeReturn ; - } } - - /* if they are both literal then */ - /* rewrite the tree */ - if (IS_LITERAL(RTYPE(tree)) && - IS_LITERAL(LTYPE(tree))) { - tree->type = EX_VALUE ; - tree->opval.val = valCompare (valFromType(LETYPE(tree)), - valFromType(RETYPE(tree)), - tree->opval.op); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + /* else they should be promotable to one another */ + else + { + if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) || + (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))))) + + if (compareType (LTYPE (tree), RTYPE (tree)) == 0) + { + werror (E_COMPARE_OP); + fprintf (stderr, "comparing type "); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, "to type "); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "\n"); + goto errorTreeReturn; + } + } + + /* if they are both literal then */ + /* rewrite the tree */ + if (IS_LITERAL (RTYPE (tree)) && + IS_LITERAL (LTYPE (tree))) + { + tree->type = EX_VALUE; + tree->opval.val = valCompare (valFromType (LETYPE (tree)), + valFromType (RETYPE (tree)), + tree->opval.op); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree ; + return tree; } - LRVAL(tree) = RRVAL(tree) = 1; - TTYPE(tree) = TETYPE(tree) = newCharLink(); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* sizeof */ - /*----------------------------*/ - case SIZEOF : /* evaluate wihout code generation */ - /* change the type to a integer */ - tree->type = EX_VALUE; - sprintf(buffer,"%d",(getSize(tree->right->ftype))); - tree->opval.val = constVal(buffer); - tree->right = tree->left = NULL; - TETYPE(tree) = getSpec(TTYPE(tree) = + LRVAL (tree) = RRVAL (tree) = 1; + TTYPE (tree) = TETYPE (tree) = newCharLink (); + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* sizeof */ +/*----------------------------*/ + case SIZEOF: /* evaluate wihout code generation */ + /* change the type to a integer */ + tree->type = EX_VALUE; + sprintf (buffer, "%d", (getSize (tree->right->ftype))); + tree->opval.val = constVal (buffer); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* conditional operator '?' */ - /*----------------------------*/ - case '?' : - /* the type is one on the left */ - TTYPE(tree) = LTYPE(tree); - TETYPE(tree)= getSpec (TTYPE(tree)); - return tree ; - - case ':' : - /* if they don't match we have a problem */ - if (checkType( LTYPE(tree), RTYPE(tree)) == 0) { - werror(E_TYPE_MISMATCH,"conditional operator"," "); - goto errorTreeReturn ; + return tree; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* conditional operator '?' */ + /*----------------------------*/ + case '?': + /* the type is value of the colon operator (on the 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 tree->right->left ; + } else { + return tree->right->right ; + } + } else { + TTYPE (tree) = RTYPE(tree); // #HACK LTYPE(tree). + TETYPE (tree) = getSpec (TTYPE (tree)); + } + return tree; + + case ':': + /* if they don't match we have a problem */ + if (compareType (LTYPE (tree), RTYPE (tree)) == 0) + { + werror (E_TYPE_MISMATCH, "conditional operator", " "); + goto errorTreeReturn; } - - TTYPE(tree) = computeType(LTYPE(tree),RTYPE(tree)); - TETYPE(tree)= getSpec(TTYPE(tree)); - return tree ; - - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* assignment operators */ - /*----------------------------*/ + + TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree)); + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* assignment operators */ +/*----------------------------*/ case MUL_ASSIGN: case DIV_ASSIGN: - /* for these it must be both must be integral */ - if (!IS_ARITHMETIC(LTYPE(tree)) || - !IS_ARITHMETIC(RTYPE(tree))) { - werror (E_OPS_INTEGRAL); - goto errorTreeReturn ; + /* for these it must be both must be integral */ + if (!IS_ARITHMETIC (LTYPE (tree)) || + !IS_ARITHMETIC (RTYPE (tree))) + { + werror (E_OPS_INTEGRAL); + goto errorTreeReturn; } - RRVAL(tree) = 1; - TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree)); + RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); - if (!tree->initMode && IS_CONSTANT(LETYPE(tree))) - werror(E_CODE_WRITE," "); + if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) + werror (E_CODE_WRITE, " "); - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"*= or /="); - goto errorTreeReturn ; + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "*= or /="); + goto errorTreeReturn; } - LLVAL(tree) = 1; - - propAsgType(tree); - - return tree ; + LLVAL (tree) = 1; + + return tree; case AND_ASSIGN: case OR_ASSIGN: case XOR_ASSIGN: case RIGHT_ASSIGN: case LEFT_ASSIGN: - /* for these it must be both must be integral */ - if (!IS_INTEGRAL(LTYPE(tree)) || - !IS_INTEGRAL(RTYPE(tree))) { - werror (E_OPS_INTEGRAL); - goto errorTreeReturn ; + /* for these it must be both must be integral */ + if (!IS_INTEGRAL (LTYPE (tree)) || + !IS_INTEGRAL (RTYPE (tree))) + { + werror (E_OPS_INTEGRAL); + goto errorTreeReturn; } - RRVAL(tree) = 1; - TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree)); + RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); - if (!tree->initMode && IS_CONSTANT(LETYPE(tree))) - werror(E_CODE_WRITE," "); + if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) + werror (E_CODE_WRITE, " "); - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"&= or |= or ^= or >>= or <<="); - goto errorTreeReturn ; + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<="); + goto errorTreeReturn; } - LLVAL(tree) = 1; - - propAsgType(tree); - - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* -= operator */ - /*----------------------------*/ + LLVAL (tree) = 1; + + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* -= operator */ +/*----------------------------*/ case SUB_ASSIGN: - if (!(IS_PTR(LTYPE(tree)) || - IS_ARITHMETIC(LTYPE(tree)))) { - werror(E_PLUS_INVALID,"-="); - goto errorTreeReturn ; + if (!(IS_PTR (LTYPE (tree)) || + IS_ARITHMETIC (LTYPE (tree)))) + { + werror (E_PLUS_INVALID, "-="); + goto errorTreeReturn; } - - if (!(IS_PTR(RTYPE(tree)) || - IS_ARITHMETIC(RTYPE(tree)))) { - werror(E_PLUS_INVALID,"-="); - goto errorTreeReturn ; + + if (!(IS_PTR (RTYPE (tree)) || + IS_ARITHMETIC (RTYPE (tree)))) + { + werror (E_PLUS_INVALID, "-="); + goto errorTreeReturn; } - RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); + RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); - if (!tree->initMode && IS_CONSTANT(LETYPE(tree))) - werror(E_CODE_WRITE," "); + if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) + werror (E_CODE_WRITE, " "); - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"-="); - goto errorTreeReturn ; + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "-="); + goto errorTreeReturn; } - LLVAL(tree) = 1; - - propAsgType(tree); - - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* += operator */ - /*----------------------------*/ + LLVAL (tree) = 1; + + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* += operator */ +/*----------------------------*/ case ADD_ASSIGN: - /* this is not a unary operation */ - /* if both pointers then problem */ - if (IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree)) ) { - werror(E_PTR_PLUS_PTR); - goto errorTreeReturn ; + /* this is not a unary operation */ + /* if both pointers then problem */ + if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) + { + werror (E_PTR_PLUS_PTR); + goto errorTreeReturn; } - - if (!IS_ARITHMETIC(LTYPE(tree)) && !IS_PTR(LTYPE(tree))) { - werror(E_PLUS_INVALID,"+="); - goto errorTreeReturn ; + + if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree))) + { + werror (E_PLUS_INVALID, "+="); + goto errorTreeReturn; } - - if (!IS_ARITHMETIC(RTYPE(tree)) && !IS_PTR(RTYPE(tree))) { - werror(E_PLUS_INVALID,"+="); - goto errorTreeReturn; + + if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree))) + { + werror (E_PLUS_INVALID, "+="); + goto errorTreeReturn; } - RRVAL(tree) = 1; - TETYPE(tree) = getSpec (TTYPE(tree) = - computeType(LTYPE(tree), - RTYPE(tree))); + RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); - if (!tree->initMode && IS_CONSTANT(LETYPE(tree))) - werror(E_CODE_WRITE," "); + if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) + werror (E_CODE_WRITE, " "); - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"+="); - goto errorTreeReturn ; + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "+="); + goto errorTreeReturn; } - tree->right = decorateType(newNode('+',copyAst(tree->left),tree->right)); - tree->opval.op = '='; - - propAsgType(tree); - - return tree; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* straight assignemnt */ - /*----------------------------*/ - case '=' : - /* cannot be an aggregate */ - if (IS_AGGREGATE(LTYPE(tree))) { - werror(E_AGGR_ASSIGN); - goto errorTreeReturn; - } - - /* they should either match or be castable */ - if (checkType (LTYPE(tree),RTYPE(tree)) == 0) { - werror(E_TYPE_MISMATCH,"assignment"," "); - fprintf(stderr,"type --> '"); - printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' "); - fprintf(stderr,"assigned to type --> '"); - printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n"); - goto errorTreeReturn ; - } + tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right)); + tree->opval.op = '='; + + return tree; - /* if the left side of the tree is of type void - then report error */ - if (IS_VOID(LTYPE(tree))) { - werror(E_CAST_ZERO); - fprintf(stderr,"type --> '"); - printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' "); - fprintf(stderr,"assigned to type --> '"); - printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n"); +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* straight assignemnt */ +/*----------------------------*/ + case '=': + /* cannot be an aggregate */ + if (IS_AGGREGATE (LTYPE (tree))) + { + werror (E_AGGR_ASSIGN); + goto errorTreeReturn; } - /* extra checks for pointer types */ - if (IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree)) && - !IS_GENPTR(LTYPE(tree))) { - if (DCL_TYPE(LTYPE(tree)) != DCL_TYPE(RTYPE(tree))) - werror(W_PTR_ASSIGN); + /* they should either match or be castable */ + if (compareType (LTYPE (tree), RTYPE (tree)) == 0) + { + werror (E_TYPE_MISMATCH, "assignment", " "); + fprintf (stderr, "type --> '"); + printTypeChain (RTYPE (tree), stderr); + fprintf (stderr, "' "); + fprintf (stderr, "assigned to type --> '"); + printTypeChain (LTYPE (tree), stderr); + fprintf (stderr, "'\n"); + goto errorTreeReturn; } - TETYPE(tree) = getSpec(TTYPE(tree) = - LTYPE(tree)); - RRVAL(tree) = 1; - LLVAL(tree) = 1; - if (!tree->initMode && IS_CONSTANT(LETYPE(tree))) - werror(E_CODE_WRITE," "); + /* if the left side of the tree is of type void + then report error */ + if (IS_VOID (LTYPE (tree))) + { + werror (E_CAST_ZERO); + printFromToType(RTYPE(tree), LTYPE(tree)); + } - if (LRVAL(tree)) { - werror(E_LVALUE_REQUIRED,"="); - goto errorTreeReturn ; + TETYPE (tree) = getSpec (TTYPE (tree) = + LTYPE (tree)); + RRVAL (tree) = 1; + LLVAL (tree) = 1; + if (!tree->initMode ) { + if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree)))) + werror (E_CODE_WRITE, " "); + } + if (LRVAL (tree)) + { + werror (E_LVALUE_REQUIRED, "="); + goto errorTreeReturn; } - propAsgType(tree); + return tree; - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* comma operator */ - /*----------------------------*/ - case ',' : - TETYPE(tree) = getSpec(TTYPE(tree) = RTYPE(tree)); - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* function call */ - /*----------------------------*/ - case CALL : - parmNumber = 1; +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* comma operator */ +/*----------------------------*/ + case ',': + TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree)); + return tree; - if (processParms (tree->left, - tree->left->args, - tree->right,&parmNumber)) - goto errorTreeReturn ; +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* function call */ +/*----------------------------*/ + case CALL: + parmNumber = 1; + + if (processParms (tree->left, + FUNC_ARGS(tree->left->ftype), + tree->right, &parmNumber, TRUE)) { + goto errorTreeReturn; + } - if (options.stackAuto || IS_RENT(LETYPE(tree))) { - tree->left->args = reverseVal(tree->left->args); - reverseParms(tree->right); + if (options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) + { + //FUNC_ARGS(tree->left->ftype) = + //reverseVal (FUNC_ARGS(tree->left->ftype)); + reverseParms (tree->right); } - tree->args = tree->left->args ; - TETYPE(tree) = getSpec (TTYPE(tree) = LTYPE(tree)->next); - return tree; + TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)->next); + return tree; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* return statement */ - /*----------------------------*/ - case RETURN : - if (!tree->right) - goto voidcheck ; +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* return statement */ +/*----------------------------*/ + case RETURN: + if (!tree->right) + goto voidcheck; - if (checkType(currFunc->type->next,RTYPE(tree)) == 0) { - werror(E_RETURN_MISMATCH); - goto errorTreeReturn ; + if (compareType (currFunc->type->next, RTYPE (tree)) == 0) + { + werror (W_RETURN_MISMATCH); + printFromToType (RTYPE(tree), currFunc->type->next); + goto errorTreeReturn; } - if (IS_VOID(currFunc->type->next) - && tree->right && - !IS_VOID(RTYPE(tree))) { - werror(E_FUNC_VOID); - goto errorTreeReturn ; + if (IS_VOID (currFunc->type->next) + && tree->right && + !IS_VOID (RTYPE (tree))) + { + werror (E_FUNC_VOID); + goto errorTreeReturn; } - - /* if there is going to be a casing required then add it */ - if (checkType(currFunc->type->next,RTYPE(tree)) < 0 ) + + /* if there is going to be a casing required then add it */ + if (compareType (currFunc->type->next, RTYPE (tree)) < 0) { -#if 0 && defined DEMAND_INTEGER_PROMOTION - if (IS_INTEGRAL(currFunc->type->next)) - { - pushTypeCastToLeaves(currFunc->type->next, tree->right, &(tree->right)); - } - else -#endif - { - tree->right = - decorateType(newNode(CAST, - newAst_LINK(copyLinkChain(currFunc->type->next)), - tree->right)); - } + tree->right = + decorateType (newNode (CAST, + newAst_LINK (copyLinkChain (currFunc->type->next)), + tree->right)); } - - RRVAL(tree) = 1; - return tree; - voidcheck : + RRVAL (tree) = 1; + return tree; - if (!IS_VOID(currFunc->type->next) && tree->right == NULL ) { - werror(E_VOID_FUNC,currFunc->name); - goto errorTreeReturn ; - } + voidcheck: - TTYPE(tree) = TETYPE(tree) = NULL ; - return tree ; + if (!IS_VOID (currFunc->type->next) && tree->right == NULL) + { + werror (E_VOID_FUNC, currFunc->name); + goto errorTreeReturn; + } - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* switch statement */ - /*----------------------------*/ + TTYPE (tree) = TETYPE (tree) = NULL; + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* switch statement */ +/*----------------------------*/ case SWITCH: - /* the switch value must be an integer */ - if (!IS_INTEGRAL(LTYPE(tree))) { - werror (E_SWITCH_NON_INTEGER); - goto errorTreeReturn ; + /* the switch value must be an integer */ + if (!IS_INTEGRAL (LTYPE (tree))) + { + werror (E_SWITCH_NON_INTEGER); + goto errorTreeReturn; } - LRVAL(tree) = 1; - TTYPE(tree) = TETYPE(tree) = NULL ; - return tree ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* ifx Statement */ - /*----------------------------*/ + LRVAL (tree) = 1; + TTYPE (tree) = TETYPE (tree) = NULL; + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* ifx Statement */ +/*----------------------------*/ case IFX: - tree->left = backPatchLabels(tree->left, - tree->trueLabel, - tree->falseLabel); - TTYPE(tree) = TETYPE(tree) = NULL; - return tree; + tree->left = backPatchLabels (tree->left, + tree->trueLabel, + tree->falseLabel); + TTYPE (tree) = TETYPE (tree) = NULL; + return tree; + +/*------------------------------------------------------------------*/ +/*----------------------------*/ + /* for Statement */ +/*----------------------------*/ + case FOR: - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* for Statement */ - /*----------------------------*/ - 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))); - decorateType(resolveSymbols(AST_FOR(tree,condExpr))); - decorateType(resolveSymbols(AST_FOR(tree,loopExpr))); - - /* if the for loop is reversible then - reverse it otherwise do what we normally - do */ - { - symbol *sym ; - ast *init, *end; - - if (isLoopReversible (tree,&sym,&init,&end)) - return reverseLoop (tree,sym,init,end); - else - return decorateType(createFor ( AST_FOR(tree,trueLabel), - AST_FOR(tree,continueLabel) , - AST_FOR(tree,falseLabel) , - AST_FOR(tree,condLabel) , - AST_FOR(tree,initExpr) , - AST_FOR(tree,condExpr) , - AST_FOR(tree,loopExpr), - tree->left ) ); - } - default : - TTYPE(tree) = TETYPE(tree) = NULL ; - return tree ; - } - - /* some error found this tree will be killed */ - errorTreeReturn : - TTYPE(tree) = TETYPE(tree) = newCharLink(); - tree->opval.op = NULLOP ; - tree->isError = 1; - - return tree ; + /* if the for loop is reversible then + reverse it otherwise do what we normally + do */ + { + symbol *sym; + ast *init, *end; + + if (isLoopReversible (tree, &sym, &init, &end)) + return reverseLoop (tree, sym, init, end); + else + return decorateType (createFor (AST_FOR (tree, trueLabel), + AST_FOR (tree, continueLabel), + AST_FOR (tree, falseLabel), + AST_FOR (tree, condLabel), + AST_FOR (tree, initExpr), + AST_FOR (tree, condExpr), + AST_FOR (tree, loopExpr), + tree->left)); + } + default: + TTYPE (tree) = TETYPE (tree) = NULL; + return tree; + } + + /* some error found this tree will be killed */ +errorTreeReturn: + TTYPE (tree) = TETYPE (tree) = newCharLink (); + tree->opval.op = NULLOP; + tree->isError = 1; + + return tree; } /*-----------------------------------------------------------------*/ /* sizeofOp - processes size of operation */ /*-----------------------------------------------------------------*/ -value *sizeofOp( sym_link *type) +value * +sizeofOp (sym_link * type) { - char buff[10]; + char buff[10]; + + /* make sure the type is complete and sane */ + checkTypeSanity(type, "(sizeof)"); - /* get the size and convert it to character */ - sprintf (buff,"%d", getSize(type)); + /* get the size and convert it to character */ + sprintf (buff, "%d", getSize (type)); - /* now convert into value */ - return constVal (buff); + /* now convert into value */ + return constVal (buff); } @@ -2920,297 +3259,326 @@ value *sizeofOp( sym_link *type) /*-----------------------------------------------------------------*/ /* backPatchLabels - change and or not operators to flow control */ /*-----------------------------------------------------------------*/ -ast *backPatchLabels (ast *tree, symbol *trueLabel, symbol *falseLabel ) -{ - - if ( ! tree ) - return NULL ; - - if ( ! (IS_ANDORNOT(tree))) - return tree ; - - /* if this an and */ - if (IS_AND(tree)) { - static int localLbl = 0 ; - symbol *localLabel ; - - sprintf (buffer,"_and_%d",localLbl++); - localLabel = newSymbol(buffer,NestLevel); - - tree->left = backPatchLabels (tree->left, localLabel,falseLabel); - - /* if left is already a IFX then just change the if true label in that */ - if (!IS_IFX(tree->left)) - tree->left = newIfxNode(tree->left,localLabel,falseLabel); - - tree->right = backPatchLabels(tree->right,trueLabel,falseLabel); - /* right is a IFX then just join */ - if (IS_IFX(tree->right)) - return newNode(NULLOP,tree->left,createLabel(localLabel,tree->right)); - - tree->right = createLabel(localLabel,tree->right); - tree->right = newIfxNode(tree->right,trueLabel,falseLabel); - - return newNode(NULLOP,tree->left,tree->right); +ast * +backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel) +{ + + if (!tree) + return NULL; + + if (!(IS_ANDORNOT (tree))) + return tree; + + /* if this an and */ + if (IS_AND (tree)) + { + static int localLbl = 0; + symbol *localLabel; + + sprintf (buffer, "_and_%d", localLbl++); + localLabel = newSymbol (buffer, NestLevel); + + tree->left = backPatchLabels (tree->left, localLabel, falseLabel); + + /* if left is already a IFX then just change the if true label in that */ + if (!IS_IFX (tree->left)) + tree->left = newIfxNode (tree->left, localLabel, falseLabel); + + tree->right = backPatchLabels (tree->right, trueLabel, falseLabel); + /* right is a IFX then just join */ + if (IS_IFX (tree->right)) + return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right)); + + tree->right = createLabel (localLabel, tree->right); + tree->right = newIfxNode (tree->right, trueLabel, falseLabel); + + return newNode (NULLOP, tree->left, tree->right); } - - /* if this is an or operation */ - if (IS_OR(tree)) { - static int localLbl = 0 ; - symbol *localLabel ; - - sprintf (buffer,"_or_%d",localLbl++); - localLabel = newSymbol(buffer,NestLevel); - - tree->left = backPatchLabels (tree->left, trueLabel,localLabel); - - /* if left is already a IFX then just change the if true label in that */ - if (!IS_IFX(tree->left)) - tree->left = newIfxNode(tree->left,trueLabel,localLabel); - - tree->right = backPatchLabels(tree->right,trueLabel,falseLabel); - /* right is a IFX then just join */ - if (IS_IFX(tree->right)) - return newNode(NULLOP,tree->left,createLabel(localLabel,tree->right)); - - tree->right = createLabel(localLabel,tree->right); - tree->right = newIfxNode(tree->right,trueLabel,falseLabel); - - return newNode(NULLOP,tree->left,tree->right); + + /* if this is an or operation */ + if (IS_OR (tree)) + { + static int localLbl = 0; + symbol *localLabel; + + sprintf (buffer, "_or_%d", localLbl++); + localLabel = newSymbol (buffer, NestLevel); + + tree->left = backPatchLabels (tree->left, trueLabel, localLabel); + + /* if left is already a IFX then just change the if true label in that */ + if (!IS_IFX (tree->left)) + tree->left = newIfxNode (tree->left, trueLabel, localLabel); + + tree->right = backPatchLabels (tree->right, trueLabel, falseLabel); + /* right is a IFX then just join */ + if (IS_IFX (tree->right)) + return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right)); + + tree->right = createLabel (localLabel, tree->right); + tree->right = newIfxNode (tree->right, trueLabel, falseLabel); + + return newNode (NULLOP, tree->left, tree->right); } - - /* change not */ - if (IS_NOT(tree)) { - int wasnot = IS_NOT(tree->left); - tree->left = backPatchLabels (tree->left,falseLabel,trueLabel); - - /* if the left is already a IFX */ - if ( ! IS_IFX(tree->left) ) - tree->left = newNode (IFX,tree->left,NULL); - - if (wasnot) { - tree->left->trueLabel = trueLabel ; - tree->left->falseLabel= falseLabel ; - } else { - tree->left->trueLabel = falseLabel ; - tree->left->falseLabel= trueLabel ; - } - return tree->left ; - } - - if (IS_IFX(tree)) { - tree->trueLabel = trueLabel ; - tree->falseLabel= falseLabel; - } - - return tree ; + + /* change not */ + if (IS_NOT (tree)) + { + int wasnot = IS_NOT (tree->left); + tree->left = backPatchLabels (tree->left, falseLabel, trueLabel); + + /* if the left is already a IFX */ + if (!IS_IFX (tree->left)) + tree->left = newNode (IFX, tree->left, NULL); + + if (wasnot) + { + tree->left->trueLabel = trueLabel; + tree->left->falseLabel = falseLabel; + } + else + { + tree->left->trueLabel = falseLabel; + tree->left->falseLabel = trueLabel; + } + return tree->left; + } + + if (IS_IFX (tree)) + { + tree->trueLabel = trueLabel; + tree->falseLabel = falseLabel; + } + + return tree; } /*-----------------------------------------------------------------*/ /* createBlock - create expression tree for block */ /*-----------------------------------------------------------------*/ -ast *createBlock ( symbol *decl, ast *body ) +ast * +createBlock (symbol * decl, ast * body) { - ast *ex ; - - /* if the block has nothing */ - if (!body) - return NULL; + ast *ex; + + /* if the block has nothing */ + if (!body) + return NULL; + + ex = newNode (BLOCK, NULL, body); + ex->values.sym = decl; + + ex->right = ex->right; + ex->level++; + ex->lineno = 0; + return ex; +} + +/*-----------------------------------------------------------------*/ +/* createLabel - creates the expression tree for labels */ +/*-----------------------------------------------------------------*/ +ast * +createLabel (symbol * label, ast * stmnt) +{ + symbol *csym; + char name[SDCC_NAME_MAX + 1]; + ast *rValue; + + /* must create fresh symbol if the symbol name */ + /* exists in the symbol table, since there can */ + /* be a variable with the same name as the labl */ + if ((csym = findSym (SymbolTab, NULL, label->name)) && + (csym->level == label->level)) + label = newSymbol (label->name, label->level); + + /* change the name before putting it in add _ */ + sprintf (name, "%s", label->name); + + /* put the label in the LabelSymbol table */ + /* but first check if a label of the same */ + /* name exists */ + if ((csym = findSym (LabelTab, NULL, name))) + werror (E_DUPLICATE_LABEL, label->name); + else + addSym (LabelTab, label, name, label->level, 0, 0); + + label->islbl = 1; + label->key = labelKey++; + rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt); + rValue->lineno = 0; + + return rValue; +} + +/*-----------------------------------------------------------------*/ +/* createCase - generates the parsetree for a case statement */ +/*-----------------------------------------------------------------*/ +ast * +createCase (ast * swStat, ast * caseVal, ast * stmnt) +{ + char caseLbl[SDCC_NAME_MAX + 1]; + ast *rexpr; + value *val; + + /* if the switch statement does not exist */ + /* then case is out of context */ + if (!swStat) + { + werror (E_CASE_CONTEXT); + return NULL; + } + + caseVal = decorateType (resolveSymbols (caseVal)); + /* if not a constant then error */ + if (!IS_LITERAL (caseVal->ftype)) + { + werror (E_CASE_CONSTANT); + return NULL; + } + + /* if not a integer than error */ + if (!IS_INTEGRAL (caseVal->ftype)) + { + werror (E_CASE_NON_INTEGER); + return NULL; + } + + /* find the end of the switch values chain */ + if (!(val = swStat->values.switchVals.swVals)) + swStat->values.switchVals.swVals = caseVal->opval.val; + else + { + /* also order the cases according to value */ + value *pval = NULL; + int cVal = (int) floatFromVal (caseVal->opval.val); + while (val && (int) floatFromVal (val) < cVal) + { + pval = val; + val = val->next; + } + + /* if we reached the end then */ + if (!val) + { + pval->next = caseVal->opval.val; + } + else + { + /* we found a value greater than */ + /* the current value we must add this */ + /* before the value */ + caseVal->opval.val->next = val; + + /* if this was the first in chain */ + if (swStat->values.switchVals.swVals == val) + swStat->values.switchVals.swVals = + caseVal->opval.val; + else + pval->next = caseVal->opval.val; + } - ex = newNode(BLOCK,NULL,body); - ex->values.sym = decl ; - - ex->right = ex->right ; - ex->level++ ; - ex->lineno = 0 ; - return ex; -} + } -/*-----------------------------------------------------------------*/ -/* createLabel - creates the expression tree for labels */ -/*-----------------------------------------------------------------*/ -ast *createLabel ( symbol *label, ast *stmnt ) -{ - symbol *csym; - char name[SDCC_NAME_MAX+1]; - ast *rValue ; - - /* must create fresh symbol if the symbol name */ - /* exists in the symbol table, since there can */ - /* be a variable with the same name as the labl */ - if ((csym = findSym (SymbolTab,NULL,label->name)) && - (csym->level == label->level)) - label = newSymbol(label->name,label->level); - - /* change the name before putting it in add _*/ - sprintf (name,"%s",label->name); - - /* put the label in the LabelSymbol table */ - /* but first check if a label of the same */ - /* name exists */ - if ( (csym = findSym(LabelTab,NULL,name))) - werror(E_DUPLICATE_LABEL,label->name); - else - addSym (LabelTab, label, name,label->level,0); - - label->islbl = 1; - label->key = labelKey++ ; - rValue = newNode (LABEL,newAst_VALUE(symbolVal(label)),stmnt); - rValue->lineno = 0; - - return rValue ; + /* create the case label */ + sprintf (caseLbl, "_case_%d_%d", + swStat->values.switchVals.swNum, + (int) floatFromVal (caseVal->opval.val)); + + rexpr = createLabel (newSymbol (caseLbl, 0), stmnt); + rexpr->lineno = 0; + return rexpr; } /*-----------------------------------------------------------------*/ -/* createCase - generates the parsetree for a case statement */ +/* createDefault - creates the parse tree for the default statement */ /*-----------------------------------------------------------------*/ -ast *createCase (ast *swStat, ast *caseVal, ast *stmnt ) +ast * +createDefault (ast * swStat, ast * stmnt) { - char caseLbl[SDCC_NAME_MAX+1]; - ast *rexpr; - value *val; - - /* if the switch statement does not exist */ - /* then case is out of context */ - if (!swStat) { - werror(E_CASE_CONTEXT); - return NULL ; - } - - caseVal = decorateType(resolveSymbols(caseVal)); - /* if not a constant then error */ - if (!IS_LITERAL(caseVal->ftype)) { - werror(E_CASE_CONSTANT); - return NULL ; - } - - /* if not a integer than error */ - if (!IS_INTEGRAL(caseVal->ftype)) { - werror(E_CASE_NON_INTEGER); - return NULL; - } + char defLbl[SDCC_NAME_MAX + 1]; - /* find the end of the switch values chain */ - if (!(val = swStat->values.switchVals.swVals)) - swStat->values.switchVals.swVals = caseVal->opval.val ; - else { - /* also order the cases according to value */ - value *pval = NULL; - int cVal = (int) floatFromVal(caseVal->opval.val); - while (val && (int) floatFromVal(val) < cVal) { - pval = val; - val = val->next ; - } - - /* if we reached the end then */ - if (!val) { - pval->next = caseVal->opval.val; - } else { - /* we found a value greater than */ - /* the current value we must add this */ - /* before the value */ - caseVal->opval.val->next = val; - - /* if this was the first in chain */ - if (swStat->values.switchVals.swVals == val) - swStat->values.switchVals.swVals = - caseVal->opval.val; - else - pval->next = caseVal->opval.val; - } - + /* if the switch statement does not exist */ + /* then case is out of context */ + if (!swStat) + { + werror (E_CASE_CONTEXT); + return NULL; } - - /* create the case label */ - sprintf(caseLbl,"_case_%d_%d", - swStat->values.switchVals.swNum, - (int) floatFromVal(caseVal->opval.val)); - - rexpr = createLabel(newSymbol(caseLbl,0),stmnt); - rexpr->lineno = 0; - return rexpr; -} -/*-----------------------------------------------------------------*/ -/* createDefault - creates the parse tree for the default statement*/ -/*-----------------------------------------------------------------*/ -ast *createDefault (ast *swStat, ast *stmnt) -{ - char defLbl[SDCC_NAME_MAX+1]; - - /* if the switch statement does not exist */ - /* then case is out of context */ - if (!swStat) { - werror(E_CASE_CONTEXT); - return NULL ; - } - - /* turn on the default flag */ - swStat->values.switchVals.swDefault = 1 ; - - /* create the label */ - sprintf (defLbl,"_default_%d",swStat->values.switchVals.swNum); - return createLabel(newSymbol(defLbl,0),stmnt); + /* turn on the default flag */ + swStat->values.switchVals.swDefault = 1; + + /* create the label */ + sprintf (defLbl, "_default_%d", swStat->values.switchVals.swNum); + return createLabel (newSymbol (defLbl, 0), stmnt); } /*-----------------------------------------------------------------*/ /* createIf - creates the parsetree for the if statement */ /*-----------------------------------------------------------------*/ -ast *createIf ( ast *condAst, ast *ifBody, ast *elseBody ) +ast * +createIf (ast * condAst, ast * ifBody, ast * elseBody) { - static int Lblnum = 0 ; - ast *ifTree ; - symbol *ifTrue , *ifFalse, *ifEnd ; - - /* if neither exists */ - if (! elseBody && !ifBody) - return condAst ; - - /* create the labels */ - sprintf (buffer,"_iffalse_%d",Lblnum); - ifFalse = newSymbol (buffer,NestLevel); - /* if no else body then end == false */ - if ( ! elseBody ) - ifEnd = ifFalse ; - else { - sprintf (buffer,"_ifend_%d",Lblnum); - ifEnd = newSymbol (buffer,NestLevel); - } - - sprintf (buffer,"_iftrue_%d",Lblnum); - ifTrue = newSymbol (buffer,NestLevel); - - Lblnum++ ; - - /* attach the ifTrue label to the top of it body */ - ifBody = createLabel(ifTrue,ifBody); - /* attach a goto end to the ifBody if else is present */ - if ( elseBody ) { - ifBody = newNode(NULLOP,ifBody, - newNode(GOTO, - newAst_VALUE(symbolVal(ifEnd)), + static int Lblnum = 0; + ast *ifTree; + symbol *ifTrue, *ifFalse, *ifEnd; + + /* if neither exists */ + if (!elseBody && !ifBody) { + // if there are no side effects (i++, j() etc) + if (!hasSEFcalls(condAst)) { + return condAst; + } + } + + /* create the labels */ + sprintf (buffer, "_iffalse_%d", Lblnum); + ifFalse = newSymbol (buffer, NestLevel); + /* if no else body then end == false */ + if (!elseBody) + ifEnd = ifFalse; + else + { + sprintf (buffer, "_ifend_%d", Lblnum); + ifEnd = newSymbol (buffer, NestLevel); + } + + sprintf (buffer, "_iftrue_%d", Lblnum); + ifTrue = newSymbol (buffer, NestLevel); + + Lblnum++; + + /* attach the ifTrue label to the top of it body */ + ifBody = createLabel (ifTrue, ifBody); + /* attach a goto end to the ifBody if else is present */ + if (elseBody) + { + ifBody = newNode (NULLOP, ifBody, + newNode (GOTO, + newAst_VALUE (symbolVal (ifEnd)), NULL)); - /* put the elseLabel on the else body */ - elseBody = createLabel (ifFalse,elseBody); - /* out the end at the end of the body */ - elseBody = newNode(NULLOP, - elseBody, - createLabel(ifEnd,NULL)); - } - else { - ifBody = newNode(NULLOP,ifBody, - createLabel(ifFalse,NULL)); - } - condAst = backPatchLabels (condAst,ifTrue,ifFalse); - if (IS_IFX(condAst)) - ifTree = condAst; - else - ifTree = newIfxNode(condAst,ifTrue,ifFalse); - - return newNode(NULLOP,ifTree, - newNode(NULLOP,ifBody,elseBody)); - + /* put the elseLabel on the else body */ + elseBody = createLabel (ifFalse, elseBody); + /* out the end at the end of the body */ + elseBody = newNode (NULLOP, + elseBody, + createLabel (ifEnd, NULL)); + } + else + { + ifBody = newNode (NULLOP, ifBody, + createLabel (ifFalse, NULL)); + } + condAst = backPatchLabels (condAst, ifTrue, ifFalse); + if (IS_IFX (condAst)) + ifTree = condAst; + else + ifTree = newIfxNode (condAst, ifTrue, ifFalse); + + return newNode (NULLOP, ifTree, + newNode (NULLOP, ifBody, elseBody)); + } /*-----------------------------------------------------------------*/ @@ -3223,41 +3591,43 @@ ast *createIf ( ast *condAst, ast *ifBody, ast *elseBody ) /* +-> falseLabel-> _dobreak_n */ /* _dobreak_n: */ /*-----------------------------------------------------------------*/ -ast *createDo ( symbol *trueLabel, symbol *continueLabel, - symbol *falseLabel, ast *condAst, ast *doBody ) +ast * +createDo (symbol * trueLabel, symbol * continueLabel, + symbol * falseLabel, ast * condAst, ast * doBody) { - ast *doTree ; - - - /* if the body does not exist then it is simple */ - if ( ! doBody ) { - condAst = backPatchLabels(condAst,continueLabel,NULL); - doTree = (IS_IFX(condAst) ? createLabel(continueLabel,condAst) - : newNode(IFX,createLabel(continueLabel,condAst),NULL)); - doTree->trueLabel = continueLabel ; - doTree->falseLabel= NULL ; - return doTree ; - } - - /* otherwise we have a body */ - condAst = backPatchLabels(condAst,trueLabel,falseLabel); - - /* attach the body label to the top */ - doBody = createLabel(trueLabel,doBody); - /* attach the continue label to end of body */ - doBody = newNode(NULLOP, doBody, - createLabel(continueLabel,NULL)); - - /* now put the break label at the end */ - if (IS_IFX(condAst)) - doTree = condAst; - else - doTree = newIfxNode(condAst,trueLabel,falseLabel); - - doTree = newNode(NULLOP,doTree,createLabel(falseLabel,NULL)); - - /* putting it together */ - return newNode(NULLOP,doBody,doTree); + ast *doTree; + + + /* if the body does not exist then it is simple */ + if (!doBody) + { + condAst = backPatchLabels (condAst, continueLabel, NULL); + doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst) + : newNode (IFX, createLabel (continueLabel, condAst), NULL)); + doTree->trueLabel = continueLabel; + doTree->falseLabel = NULL; + return doTree; + } + + /* otherwise we have a body */ + condAst = backPatchLabels (condAst, trueLabel, falseLabel); + + /* attach the body label to the top */ + doBody = createLabel (trueLabel, doBody); + /* attach the continue label to end of body */ + doBody = newNode (NULLOP, doBody, + createLabel (continueLabel, NULL)); + + /* now put the break label at the end */ + if (IS_IFX (condAst)) + doTree = condAst; + else + doTree = newIfxNode (condAst, trueLabel, falseLabel); + + doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL)); + + /* putting it together */ + return newNode (NULLOP, doBody, doTree); } /*-----------------------------------------------------------------*/ @@ -3274,48 +3644,49 @@ ast *createDo ( symbol *trueLabel, symbol *continueLabel, /* goto _forcond_n ; */ /* _forbreak_n: */ /*-----------------------------------------------------------------*/ -ast *createFor ( symbol *trueLabel, symbol *continueLabel , - symbol *falseLabel,symbol *condLabel , - ast *initExpr, ast *condExpr, ast *loopExpr, - ast *forBody ) +ast * +createFor (symbol * trueLabel, symbol * continueLabel, + symbol * falseLabel, symbol * condLabel, + ast * initExpr, ast * condExpr, ast * loopExpr, + ast * forBody) { - ast *forTree ; - - /* if loopexpression not present then we can generate it */ - /* the same way as a while */ - if ( ! loopExpr ) - return newNode(NULLOP,initExpr, - createWhile (trueLabel, continueLabel, - falseLabel,condExpr, forBody )); - /* vanilla for statement */ - condExpr = backPatchLabels(condExpr,trueLabel,falseLabel); - - if (condExpr && !IS_IFX(condExpr)) - condExpr = newIfxNode(condExpr,trueLabel,falseLabel); - - - /* attach condition label to condition */ - condExpr = createLabel(condLabel,condExpr); - - /* attach body label to body */ - forBody = createLabel(trueLabel,forBody); - - /* attach continue to forLoop expression & attach */ - /* goto the forcond @ and of loopExpression */ - loopExpr = createLabel(continueLabel, - newNode(NULLOP, + ast *forTree; + + /* if loopexpression not present then we can generate it */ + /* the same way as a while */ + if (!loopExpr) + return newNode (NULLOP, initExpr, + createWhile (trueLabel, continueLabel, + falseLabel, condExpr, forBody)); + /* vanilla for statement */ + condExpr = backPatchLabels (condExpr, trueLabel, falseLabel); + + if (condExpr && !IS_IFX (condExpr)) + condExpr = newIfxNode (condExpr, trueLabel, falseLabel); + + + /* attach condition label to condition */ + condExpr = createLabel (condLabel, condExpr); + + /* attach body label to body */ + forBody = createLabel (trueLabel, forBody); + + /* attach continue to forLoop expression & attach */ + /* goto the forcond @ and of loopExpression */ + loopExpr = createLabel (continueLabel, + newNode (NULLOP, loopExpr, - newNode(GOTO, - newAst_VALUE(symbolVal(condLabel)), - NULL))); - /* now start putting them together */ - forTree = newNode(NULLOP,initExpr,condExpr); - forTree = newNode(NULLOP,forTree,forBody); - forTree = newNode(NULLOP,forTree,loopExpr); - /* finally add the break label */ - forTree = newNode(NULLOP,forTree, - createLabel(falseLabel,NULL)); - return forTree ; + newNode (GOTO, + newAst_VALUE (symbolVal (condLabel)), + NULL))); + /* now start putting them together */ + forTree = newNode (NULLOP, initExpr, condExpr); + forTree = newNode (NULLOP, forTree, forBody); + forTree = newNode (NULLOP, forTree, loopExpr); + /* finally add the break label */ + forTree = newNode (NULLOP, forTree, + createLabel (falseLabel, NULL)); + return forTree; } /*-----------------------------------------------------------------*/ @@ -3325,378 +3696,401 @@ ast *createFor ( symbol *trueLabel, symbol *continueLabel , /* _while_continue_n: */ /* condition_expression +-> trueLabel -> _while_boby_n */ /* | */ -/* +-> falseLabel -> _while_break_n*/ +/* +-> falseLabel -> _while_break_n */ /* _while_body_n: */ /* statements */ /* goto _while_continue_n */ /* _while_break_n: */ /*-----------------------------------------------------------------*/ -ast *createWhile (symbol *trueLabel, symbol *continueLabel, - symbol *falseLabel,ast *condExpr, ast *whileBody ) +ast * +createWhile (symbol * trueLabel, symbol * continueLabel, + symbol * falseLabel, ast * condExpr, ast * whileBody) { - ast *whileTree ; - - /* put the continue label */ - condExpr = backPatchLabels (condExpr,trueLabel,falseLabel); - condExpr = createLabel(continueLabel,condExpr); - condExpr->lineno = 0; - - /* put the body label in front of the body */ - whileBody = createLabel(trueLabel,whileBody); - whileBody->lineno = 0; - /* put a jump to continue at the end of the body */ - /* and put break label at the end of the body */ - whileBody = newNode(NULLOP, - whileBody, - newNode(GOTO, - newAst_VALUE(symbolVal(continueLabel)), - createLabel(falseLabel,NULL))); - - /* put it all together */ - if ( IS_IFX(condExpr) ) - whileTree = condExpr ; - else { - whileTree = newNode (IFX, condExpr,NULL ); - /* put the true & false labels in place */ - whileTree->trueLabel = trueLabel ; - whileTree->falseLabel= falseLabel; - } - - return newNode(NULLOP,whileTree,whileBody ); + ast *whileTree; + + /* put the continue label */ + condExpr = backPatchLabels (condExpr, trueLabel, falseLabel); + condExpr = createLabel (continueLabel, condExpr); + condExpr->lineno = 0; + + /* put the body label in front of the body */ + whileBody = createLabel (trueLabel, whileBody); + whileBody->lineno = 0; + /* put a jump to continue at the end of the body */ + /* and put break label at the end of the body */ + whileBody = newNode (NULLOP, + whileBody, + newNode (GOTO, + newAst_VALUE (symbolVal (continueLabel)), + createLabel (falseLabel, NULL))); + + /* put it all together */ + if (IS_IFX (condExpr)) + whileTree = condExpr; + else + { + whileTree = newNode (IFX, condExpr, NULL); + /* put the true & false labels in place */ + whileTree->trueLabel = trueLabel; + whileTree->falseLabel = falseLabel; + } + + return newNode (NULLOP, whileTree, whileBody); } /*-----------------------------------------------------------------*/ /* optimizeGetHbit - get highest order bit of the expression */ /*-----------------------------------------------------------------*/ -ast *optimizeGetHbit (ast *tree) +ast * +optimizeGetHbit (ast * tree) { - int i,j; - /* if this is not a bit and */ - if (!IS_BITAND(tree)) - return tree; - - /* will look for tree of the form - ( expr >> ((sizeof expr) -1) ) & 1 */ - if (!IS_AST_LIT_VALUE(tree->right)) - return tree; + int i, j; + /* if this is not a bit and */ + if (!IS_BITAND (tree)) + return tree; - if (AST_LIT_VALUE(tree->right) != 1) - return tree; + /* will look for tree of the form + ( expr >> ((sizeof expr) -1) ) & 1 */ + if (!IS_AST_LIT_VALUE (tree->right)) + return tree; - if (!IS_RIGHT_OP(tree->left)) - return tree; + if (AST_LIT_VALUE (tree->right) != 1) + return tree; - if (!IS_AST_LIT_VALUE(tree->left->right)) - return tree; + if (!IS_RIGHT_OP (tree->left)) + return tree; - if ((i = AST_LIT_VALUE(tree->left->right)) != - ( j = (getSize(TTYPE(tree->left->left))*8 - 1))) - return tree; + if (!IS_AST_LIT_VALUE (tree->left->right)) + return tree; + + if ((i = (int) AST_LIT_VALUE (tree->left->right)) != + (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) + return tree; + + return decorateType (newNode (GETHBIT, tree->left->left, NULL)); - return decorateType(newNode(GETHBIT,tree->left->left,NULL)); - } /*-----------------------------------------------------------------*/ /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */ /*-----------------------------------------------------------------*/ -ast *optimizeRRCRLC ( ast *root ) +ast * +optimizeRRCRLC (ast * root) { - /* will look for trees of the form - (?expr << 1) | (?expr >> 7) or - (?expr >> 7) | (?expr << 1) will make that - into a RLC : operation .. - Will also look for - (?expr >> 1) | (?expr << 7) or - (?expr << 7) | (?expr >> 1) will make that - into a RRC operation - note : by 7 I mean (number of bits required to hold the - variable -1 ) */ - /* if the root operations is not a | operation the not */ - if (!IS_BITOR(root)) - return root ; - - /* I have to think of a better way to match patterns this sucks */ - /* that aside let start looking for the first case : I use a the - negative check a lot to improve the efficiency */ - /* (?expr << 1) | (?expr >> 7) */ - if (IS_LEFT_OP(root->left) && - IS_RIGHT_OP(root->right) ) { - - if (!SPEC_USIGN(TETYPE(root->left->left))) - return root; + /* will look for trees of the form + (?expr << 1) | (?expr >> 7) or + (?expr >> 7) | (?expr << 1) will make that + into a RLC : operation .. + Will also look for + (?expr >> 1) | (?expr << 7) or + (?expr << 7) | (?expr >> 1) will make that + into a RRC operation + note : by 7 I mean (number of bits required to hold the + variable -1 ) */ + /* if the root operations is not a | operation the not */ + if (!IS_BITOR (root)) + return root; - if (!IS_AST_LIT_VALUE(root->left->right) || - !IS_AST_LIT_VALUE(root->right->right)) - goto tryNext0; + /* I have to think of a better way to match patterns this sucks */ + /* that aside let start looking for the first case : I use a the + negative check a lot to improve the efficiency */ + /* (?expr << 1) | (?expr >> 7) */ + if (IS_LEFT_OP (root->left) && + IS_RIGHT_OP (root->right)) + { - /* make sure it is the same expression */ - if (!isAstEqual(root->left->left, - root->right->left)) - goto tryNext0; - - if (AST_LIT_VALUE(root->left->right) != 1 ) - goto tryNext0 ; - - if (AST_LIT_VALUE(root->right->right) != - (getSize(TTYPE(root->left->left))*8 - 1)) - goto tryNext0 ; + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; - /* whew got the first case : create the AST */ - return newNode(RLC,root->left->left,NULL); + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + goto tryNext0; + + /* make sure it is the same expression */ + if (!isAstEqual (root->left->left, + root->right->left)) + goto tryNext0; + + if (AST_LIT_VALUE (root->left->right) != 1) + goto tryNext0; + + if (AST_LIT_VALUE (root->right->right) != + (getSize (TTYPE (root->left->left)) * 8 - 1)) + goto tryNext0; + + /* whew got the first case : create the AST */ + return newNode (RLC, root->left->left, NULL); } - tryNext0: - /* check for second case */ - /* (?expr >> 7) | (?expr << 1) */ - if (IS_LEFT_OP(root->right) && - IS_RIGHT_OP(root->left) ) { +tryNext0: + /* check for second case */ + /* (?expr >> 7) | (?expr << 1) */ + if (IS_LEFT_OP (root->right) && + IS_RIGHT_OP (root->left)) + { - if (!SPEC_USIGN(TETYPE(root->left->left))) - return root; - - if (!IS_AST_LIT_VALUE(root->left->right) || - !IS_AST_LIT_VALUE(root->right->right)) - goto tryNext1 ; - - /* make sure it is the same symbol */ - if (!isAstEqual(root->left->left, - root->right->left)) - goto tryNext1 ; - - if (AST_LIT_VALUE(root->right->right) != 1 ) - goto tryNext1 ; - - if (AST_LIT_VALUE(root->left->right) != - (getSize(TTYPE(root->left->left))*8 - 1)) - goto tryNext1 ; + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; + + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + goto tryNext1; + + /* make sure it is the same symbol */ + if (!isAstEqual (root->left->left, + root->right->left)) + goto tryNext1; + + if (AST_LIT_VALUE (root->right->right) != 1) + goto tryNext1; + + if (AST_LIT_VALUE (root->left->right) != + (getSize (TTYPE (root->left->left)) * 8 - 1)) + goto tryNext1; + + /* whew got the first case : create the AST */ + return newNode (RLC, root->left->left, NULL); - /* whew got the first case : create the AST */ - return newNode(RLC,root->left->left,NULL); - } - tryNext1: - /* third case for RRC */ - /* (?symbol >> 1) | (?symbol << 7) */ - if (IS_LEFT_OP(root->right) && - IS_RIGHT_OP(root->left) ) { +tryNext1: + /* third case for RRC */ + /* (?symbol >> 1) | (?symbol << 7) */ + if (IS_LEFT_OP (root->right) && + IS_RIGHT_OP (root->left)) + { - if (!SPEC_USIGN(TETYPE(root->left->left))) - return root; - - if (!IS_AST_LIT_VALUE(root->left->right) || - !IS_AST_LIT_VALUE(root->right->right)) - goto tryNext2; - - /* make sure it is the same symbol */ - if (!isAstEqual(root->left->left, - root->right->left)) - goto tryNext2; - - if (AST_LIT_VALUE(root->left->right) != 1 ) - goto tryNext2; - - if (AST_LIT_VALUE(root->right->right) != - (getSize(TTYPE(root->left->left))*8 - 1)) - goto tryNext2; + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; + + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + goto tryNext2; + + /* make sure it is the same symbol */ + if (!isAstEqual (root->left->left, + root->right->left)) + goto tryNext2; + + if (AST_LIT_VALUE (root->left->right) != 1) + goto tryNext2; + + if (AST_LIT_VALUE (root->right->right) != + (getSize (TTYPE (root->left->left)) * 8 - 1)) + goto tryNext2; + + /* whew got the first case : create the AST */ + return newNode (RRC, root->left->left, NULL); - /* whew got the first case : create the AST */ - return newNode(RRC,root->left->left,NULL); - } - tryNext2: - /* fourth and last case for now */ - /* (?symbol << 7) | (?symbol >> 1) */ - if (IS_RIGHT_OP(root->right) && - IS_LEFT_OP(root->left) ) { +tryNext2: + /* fourth and last case for now */ + /* (?symbol << 7) | (?symbol >> 1) */ + if (IS_RIGHT_OP (root->right) && + IS_LEFT_OP (root->left)) + { - 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 symbol */ - if (!isAstEqual(root->left->left, - root->right->left)) - return root; - - if (AST_LIT_VALUE(root->right->right) != 1 ) - return root ; - - if (AST_LIT_VALUE(root->left->right) != - (getSize(TTYPE(root->left->left))*8 - 1)) - return root ; + 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 symbol */ + if (!isAstEqual (root->left->left, + root->right->left)) + return root; + + if (AST_LIT_VALUE (root->right->right) != 1) + return root; + + if (AST_LIT_VALUE (root->left->right) != + (getSize (TTYPE (root->left->left)) * 8 - 1)) + return root; + + /* whew got the first case : create the AST */ + return newNode (RRC, root->left->left, NULL); - /* whew got the first case : create the AST */ - return newNode(RRC,root->left->left,NULL); - } - /* not found return root */ - return root; + /* not found return root */ + return root; } /*-----------------------------------------------------------------*/ -/* optimizeCompare - otimizes compares for bit variables */ +/* optimizeCompare - otimizes compares for bit variables */ /*-----------------------------------------------------------------*/ -ast *optimizeCompare ( ast *root ) +ast * +optimizeCompare (ast * root) { - ast *optExpr = NULL; - value *vleft; - value *vright; - unsigned int litValue ; - - /* if nothing then return nothing */ - if (!root) - return NULL ; - - /* if not a compare op then do leaves */ - if (!IS_COMPARE_OP(root)) { - root->left = optimizeCompare (root->left); - root->right= optimizeCompare (root->right); - return root ; - } - - /* if left & right are the same then depending - of the operation do */ - if (isAstEqual(root->left,root->right)) { - switch (root->opval.op) { - case '>' : - case '<' : - case NE_OP : - optExpr = newAst_VALUE(constVal("0")); - break; - case GE_OP : - case LE_OP : - case EQ_OP : - optExpr = newAst_VALUE(constVal("1")); - break; + ast *optExpr = NULL; + value *vleft; + value *vright; + unsigned int litValue; + + /* if nothing then return nothing */ + if (!root) + return NULL; + + /* if not a compare op then do leaves */ + if (!IS_COMPARE_OP (root)) + { + root->left = optimizeCompare (root->left); + root->right = optimizeCompare (root->right); + return root; + } + + /* if left & right are the same then depending + of the operation do */ + if (isAstEqual (root->left, root->right)) + { + switch (root->opval.op) + { + case '>': + case '<': + case NE_OP: + optExpr = newAst_VALUE (constVal ("0")); + break; + case GE_OP: + case LE_OP: + case EQ_OP: + optExpr = newAst_VALUE (constVal ("1")); + break; } - return decorateType(optExpr); + return decorateType (optExpr); } - vleft = (root->left->type == EX_VALUE ? - root->left->opval.val : NULL ); - - vright = (root->right->type == EX_VALUE ? - root->right->opval.val : NULL); - - /* if left is a BITVAR in BITSPACE */ - /* and right is a LITERAL then opt-*/ - /* imize else do nothing */ - if (vleft && vright && - IS_BITVAR(vleft->etype) && - IN_BITSPACE(SPEC_OCLS(vleft->etype)) && - IS_LITERAL(vright->etype)) { - - /* if right side > 1 then comparison may never succeed */ - if ( (litValue = (int) floatFromVal(vright)) > 1 ) { - werror(W_BAD_COMPARE); - goto noOptimize ; + vleft = (root->left->type == EX_VALUE ? + root->left->opval.val : NULL); + + vright = (root->right->type == EX_VALUE ? + root->right->opval.val : NULL); + + /* if left is a BITVAR in BITSPACE */ + /* and right is a LITERAL then opt- */ + /* imize else do nothing */ + if (vleft && vright && + IS_BITVAR (vleft->etype) && + IN_BITSPACE (SPEC_OCLS (vleft->etype)) && + IS_LITERAL (vright->etype)) + { + + /* if right side > 1 then comparison may never succeed */ + if ((litValue = (int) floatFromVal (vright)) > 1) + { + werror (W_BAD_COMPARE); + goto noOptimize; } - - if ( litValue ) { - switch (root->opval.op) { - case '>' : /* bit value greater than 1 cannot be */ - werror(W_BAD_COMPARE); - goto noOptimize ; - break; - - case '<' : /* bit value < 1 means 0 */ - case NE_OP : - optExpr = newNode('!',newAst_VALUE(vleft),NULL); - break; - - case LE_OP : /* bit value <= 1 means no check */ - optExpr = newAst_VALUE(vright); - break; - - case GE_OP : /* bit value >= 1 means only check for = */ - case EQ_OP : - optExpr = newAst_VALUE(vleft); - break; + + if (litValue) + { + switch (root->opval.op) + { + case '>': /* bit value greater than 1 cannot be */ + werror (W_BAD_COMPARE); + goto noOptimize; + break; + + case '<': /* bit value < 1 means 0 */ + case NE_OP: + optExpr = newNode ('!', newAst_VALUE (vleft), NULL); + break; + + case LE_OP: /* bit value <= 1 means no check */ + optExpr = newAst_VALUE (vright); + break; + + case GE_OP: /* bit value >= 1 means only check for = */ + case EQ_OP: + optExpr = newAst_VALUE (vleft); + break; } - } else { /* literal is zero */ - switch (root->opval.op) { - case '<' : /* bit value < 0 cannot be */ - werror(W_BAD_COMPARE); - goto noOptimize ; - break; - - case '>' : /* bit value > 0 means 1 */ - case NE_OP : - optExpr = newAst_VALUE(vleft); - break; - - case LE_OP : /* bit value <= 0 means no check */ - case GE_OP : /* bit value >= 0 means no check */ - werror(W_BAD_COMPARE); - goto noOptimize ; - break; - - case EQ_OP : /* bit == 0 means ! of bit */ - optExpr = newNode('!',newAst_VALUE(vleft),NULL); - break; + } + else + { /* literal is zero */ + switch (root->opval.op) + { + case '<': /* bit value < 0 cannot be */ + werror (W_BAD_COMPARE); + goto noOptimize; + break; + + case '>': /* bit value > 0 means 1 */ + case NE_OP: + optExpr = newAst_VALUE (vleft); + break; + + case LE_OP: /* bit value <= 0 means no check */ + case GE_OP: /* bit value >= 0 means no check */ + werror (W_BAD_COMPARE); + goto noOptimize; + break; + + case EQ_OP: /* bit == 0 means ! of bit */ + optExpr = newNode ('!', newAst_VALUE (vleft), NULL); + break; } - } - return decorateType(resolveSymbols(optExpr)); - } /* end-of-if of BITVAR */ - - noOptimize : - return root; + } + return decorateType (resolveSymbols (optExpr)); + } /* end-of-if of BITVAR */ + +noOptimize: + return root; } /*-----------------------------------------------------------------*/ /* addSymToBlock : adds the symbol to the first block we find */ /*-----------------------------------------------------------------*/ -void addSymToBlock (symbol *sym, ast *tree) +void +addSymToBlock (symbol * sym, ast * tree) { - /* reached end of tree or a leaf */ - if (!tree || IS_AST_LINK(tree) || IS_AST_VALUE(tree)) - return ; + /* reached end of tree or a leaf */ + if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree)) + return; - /* found a block */ - if (IS_AST_OP(tree) && - tree->opval.op == BLOCK ) { - - symbol *lsym = copySymbol(sym); - - lsym->next = AST_VALUES(tree,sym); - AST_VALUES(tree,sym) = lsym ; - return ; + /* found a block */ + if (IS_AST_OP (tree) && + tree->opval.op == BLOCK) + { + + symbol *lsym = copySymbol (sym); + + lsym->next = AST_VALUES (tree, sym); + AST_VALUES (tree, sym) = lsym; + return; } - - addSymToBlock(sym,tree->left); - addSymToBlock(sym,tree->right); + + addSymToBlock (sym, tree->left); + addSymToBlock (sym, tree->right); } /*-----------------------------------------------------------------*/ /* processRegParms - do processing for register parameters */ /*-----------------------------------------------------------------*/ -static void processRegParms (value *args, ast *body) +static void +processRegParms (value * args, ast * body) { - while (args) { - if (IS_REGPARM(args->etype)) - addSymToBlock(args->sym,body); - args = args->next; + while (args) + { + if (IS_REGPARM (args->etype)) + addSymToBlock (args->sym, body); + args = args->next; } } /*-----------------------------------------------------------------*/ /* resetParmKey - resets the operandkeys for the symbols */ /*-----------------------------------------------------------------*/ -DEFSETFUNC(resetParmKey) +DEFSETFUNC (resetParmKey) { - symbol *sym = item; + symbol *sym = item; - sym->key = 0 ; - sym->defs = NULL ; - sym->uses = NULL ; - sym->remat= 0; - return 1; + sym->key = 0; + sym->defs = NULL; + sym->uses = NULL; + sym->remat = 0; + return 1; } /*-----------------------------------------------------------------*/ @@ -3705,137 +4099,823 @@ DEFSETFUNC(resetParmKey) /* is generated function by function, later when */ /* add inter-procedural analysis this will change */ /*-----------------------------------------------------------------*/ -ast *createFunction (symbol *name, ast *body ) +ast * +createFunction (symbol * name, ast * body) { - ast *ex ; - symbol *csym; - int stack = 0 ; - sym_link *fetype; - iCode *piCode = NULL; - - /* if check function return 0 then some problem */ - if (checkFunction (name) == 0) - return NULL; - - /* create a dummy block if none exists */ - if (!body) - body = newNode(BLOCK,NULL,NULL); - - noLineno++ ; - - /* check if the function name already in the symbol table */ - if ((csym = findSym (SymbolTab,NULL,name->name))) { - name = csym ; - /* special case for compiler defined functions - we need to add the name to the publics list : this - actually means we are now compiling the compiler - support routine */ - if (name->cdef) { - addSet(&publics,name); - } - } - else { - addSymChain(name); - allocVariables(name); - } - name->lastLine = yylineno; - currFunc = name ; - processFuncArgs(currFunc,0); - - /* set the stack pointer */ - /* PENDING: check this for the mcs51 */ - stackPtr = -port->stack.direction * port->stack.call_overhead; - if (IS_ISR(name->etype)) - stackPtr -= port->stack.direction * port->stack.isr_overhead; - if (IS_RENT(name->etype) || options.stackAuto) - stackPtr -= port->stack.direction * port->stack.reent_overhead; - - xstackPtr = -port->stack.direction * port->stack.call_overhead; - - fetype = getSpec(name->type); /* get the specifier for the function */ - /* if this is a reentrant function then */ - if (IS_RENT(fetype)) - reentrant++ ; - - allocParms (name->args); /* allocate the parameters */ - - /* do processing for parameters that are passed in registers */ - processRegParms (name->args,body); - - /* set the stack pointer */ - stackPtr = 0; - xstackPtr= -1; - - /* allocate & autoinit the block variables */ - processBlockVars (body, &stack,ALLOCATE); - - /* save the stack information */ - if (options.useXstack) - name->xstack = SPEC_STAK(fetype) = stack; - else - name->stack = SPEC_STAK(fetype) = stack; - - /* name needs to be mangled */ - sprintf (name->rname,"%s%s", port->fun_prefix, name->name); - - body = resolveSymbols(body); /* resolve the symbols */ - body = decorateType (body); /* propagateType & do semantic checks */ - - ex = newAst_VALUE(symbolVal(name)); /* create name */ - ex = newNode (FUNCTION,ex,body); - ex->values.args = name->args ; - - if (fatalError) { - werror(E_FUNC_NO_CODE,name->name); - goto skipall ; - } - - /* create the node & generate intermediate code */ - codeOutFile = code->oFile; - piCode = iCodeFromAst(ex); - - if (fatalError) { - werror(E_FUNC_NO_CODE,name->name); - goto skipall ; - } - - eBBlockFromiCode(piCode); - - /* if there are any statics then do them */ - if (staticAutos) { - codeOutFile = statsg->oFile; - eBBlockFromiCode (iCodeFromAst (decorateType(resolveSymbols(staticAutos)))); - staticAutos = NULL; - } - - skipall: - - /* dealloc the block variables */ - processBlockVars(body, &stack,DEALLOCATE); - /* deallocate paramaters */ - deallocParms(name->args); - - if (IS_RENT(fetype)) - reentrant-- ; - - /* we are done freeup memory & cleanup */ - noLineno-- ; - labelKey = 1 ; - name->key = 0; - name->fbody = 1; - addSet(&operKeyReset,name); - applyToSet(operKeyReset,resetParmKey); - - if (options.debug && !options.nodebug) - cdbStructBlock(1,cdbFile); - - cleanUpLevel(LabelTab,0); - cleanUpBlock(StructTab,1); - cleanUpBlock(TypedefTab,1); - - xstack->syms = NULL; - istack->syms = NULL; - return NULL ; + ast *ex; + symbol *csym; + int stack = 0; + sym_link *fetype; + iCode *piCode = NULL; + + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) + fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name); + + /* if check function return 0 then some problem */ + if (checkFunction (name, NULL) == 0) + return NULL; + + /* create a dummy block if none exists */ + if (!body) + body = newNode (BLOCK, NULL, NULL); + + noLineno++; + + /* check if the function name already in the symbol table */ + if ((csym = findSym (SymbolTab, NULL, name->name))) + { + name = csym; + /* special case for compiler defined functions + we need to add the name to the publics list : this + actually means we are now compiling the compiler + support routine */ + if (name->cdef) + { + addSet (&publics, name); + } + } + else + { + addSymChain (name); + allocVariables (name); + } + name->lastLine = yylineno; + currFunc = name; + +#if 0 // jwk: this is now done in addDecl() + processFuncArgs (currFunc); +#endif + + /* set the stack pointer */ + /* PENDING: check this for the mcs51 */ + stackPtr = -port->stack.direction * port->stack.call_overhead; + if (IFFUNC_ISISR (name->type)) + stackPtr -= port->stack.direction * port->stack.isr_overhead; + if (IFFUNC_ISREENT (name->type) || options.stackAuto) + stackPtr -= port->stack.direction * port->stack.reent_overhead; + + xstackPtr = -port->stack.direction * port->stack.call_overhead; + + fetype = getSpec (name->type); /* get the specifier for the function */ + /* if this is a reentrant function then */ + if (IFFUNC_ISREENT (name->type)) + reentrant++; + + allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */ + + /* do processing for parameters that are passed in registers */ + processRegParms (FUNC_ARGS(name->type), body); + + /* set the stack pointer */ + stackPtr = 0; + xstackPtr = -1; + + /* allocate & autoinit the block variables */ + processBlockVars (body, &stack, ALLOCATE); + + /* save the stack information */ + if (options.useXstack) + name->xstack = SPEC_STAK (fetype) = stack; + else + name->stack = SPEC_STAK (fetype) = stack; + + /* name needs to be mangled */ + sprintf (name->rname, "%s%s", port->fun_prefix, name->name); + + body = resolveSymbols (body); /* resolve the symbols */ + body = decorateType (body); /* propagateType & do semantic checks */ + + ex = newAst_VALUE (symbolVal (name)); /* create name */ + ex = newNode (FUNCTION, ex, body); + ex->values.args = FUNC_ARGS(name->type); + ex->decorated=1; + if (options.dump_tree) PA(ex); + if (fatalError) + { + werror (E_FUNC_NO_CODE, name->name); + goto skipall; + } + + /* create the node & generate intermediate code */ + GcurMemmap = code; + codeOutFile = code->oFile; + piCode = iCodeFromAst (ex); + + if (fatalError) + { + werror (E_FUNC_NO_CODE, name->name); + goto skipall; + } + + eBBlockFromiCode (piCode); + + /* if there are any statics then do them */ + if (staticAutos) + { + GcurMemmap = statsg; + codeOutFile = statsg->oFile; + eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos)))); + staticAutos = NULL; + } + +skipall: + + /* dealloc the block variables */ + processBlockVars (body, &stack, DEALLOCATE); + /* deallocate paramaters */ + deallocParms (FUNC_ARGS(name->type)); + + if (IFFUNC_ISREENT (name->type)) + reentrant--; + + /* we are done freeup memory & cleanup */ + noLineno--; + labelKey = 1; + name->key = 0; + FUNC_HASBODY(name->type) = 1; + addSet (&operKeyReset, name); + applyToSet (operKeyReset, resetParmKey); + + if (options.debug) + cdbStructBlock (1, cdbFile); + + cleanUpLevel (LabelTab, 0); + cleanUpBlock (StructTab, 1); + cleanUpBlock (TypedefTab, 1); + + xstack->syms = NULL; + istack->syms = NULL; + return NULL; } +#define INDENT(x,f) { int i ; for (i=0;i < x; i++) fprintf(f," "); } +/*-----------------------------------------------------------------*/ +/* ast_print : prints the ast (for debugging purposes) */ +/*-----------------------------------------------------------------*/ + +void ast_print (ast * tree, FILE *outfile, int indent) +{ + + if (!tree) return ; + + /* can print only decorated trees */ + if (!tree->decorated) return; + + /* if any child is an error | this one is an error do nothing */ + if (tree->isError || + (tree->left && tree->left->isError) || + (tree->right && tree->right->isError)) { + fprintf(outfile,"ERROR_NODE(%p)\n",tree); + } + + + /* print the line */ + /* if not block & function */ + if (tree->type == EX_OP && + (tree->opval.op != FUNCTION && + 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 (", + tree->left->opval.val->name, tree); + printTypeChain (tree->ftype,outfile); + fprintf(outfile,") args ("); + do { + if (arg) { + fprintf (outfile, ", "); + } + printTypeChain (args ? args->type : NULL, outfile); + arg++; + args= args ? args->next : NULL; + } while (args); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent); + ast_print(tree->right,outfile,indent); + return ; + } + if (tree->opval.op == BLOCK) { + symbol *decls = tree->values.sym; + INDENT(indent,outfile); + fprintf(outfile,"{\n"); + while (decls) { + INDENT(indent+4,outfile); + fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (", + decls->name, decls); + printTypeChain(decls->type,outfile); + fprintf(outfile,")\n"); + + decls = decls->next; + } + ast_print(tree->right,outfile,indent+4); + INDENT(indent,outfile); + fprintf(outfile,"}\n"); + return; + } + if (tree->opval.op == NULLOP) { + fprintf(outfile,"\n"); + ast_print(tree->left,outfile,indent); + fprintf(outfile,"\n"); + ast_print(tree->right,outfile,indent); + return ; + } + INDENT(indent,outfile); + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* leaf has been reached */ + /*----------------------------*/ + /* if this is of type value */ + /* 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)); + } else if (tree->opval.val->sym) { + /* if the undefined flag is set then give error message */ + if (tree->opval.val->sym->undefined) { + fprintf(outfile,"UNDEFINED SYMBOL "); + } else { + fprintf(outfile,"SYMBOL "); + } + fprintf(outfile,"(%s=%p)", + tree->opval.val->sym->name,tree); + } + if (tree->ftype) { + fprintf(outfile," type ("); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + } else { + fprintf(outfile,"\n"); + } + return ; + } + + /* if type link for the case of cast */ + if (tree->type == EX_LINK) { + fprintf(outfile,"TYPENODE (%p) type = (",tree); + printTypeChain(tree->opval.lnk,outfile); + fprintf(outfile,")\n"); + return ; + } + + + /* depending on type of operator do */ + + switch (tree->opval.op) { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* array node */ + /*----------------------------*/ + case '[': + fprintf(outfile,"ARRAY_OP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* struct/union */ + /*----------------------------*/ + case '.': + fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* struct/union pointer */ + /*----------------------------*/ + case PTR_OP: + fprintf(outfile,"PTR_ACCESS (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* ++/-- operation */ + /*----------------------------*/ + case INC_OP: /* incerement operator unary so left only */ + fprintf(outfile,"INC_OP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + + case DEC_OP: + fprintf(outfile,"DEC_OP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* bitwise and */ + /*----------------------------*/ + case '&': + if (tree->right) { + fprintf(outfile,"& (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + } else { + fprintf(outfile,"ADDRESS_OF (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + } + return ; + /*----------------------------*/ + /* bitwise or */ + /*----------------------------*/ + case '|': + fprintf(outfile,"OR (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* bitwise xor */ + /*----------------------------*/ + case '^': + fprintf(outfile,"XOR (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* division */ + /*----------------------------*/ + case '/': + fprintf(outfile,"DIV (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* modulus */ + /*----------------------------*/ + case '%': + fprintf(outfile,"MOD (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* address dereference */ + /*----------------------------*/ + case '*': /* can be unary : if right is null then unary operation */ + if (!tree->right) { + fprintf(outfile,"DEREF (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + } + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* multiplication */ + /*----------------------------*/ + fprintf(outfile,"MULT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* unary '+' operator */ + /*----------------------------*/ + case '+': + /* if unary plus */ + if (!tree->right) { + fprintf(outfile,"UPLUS (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + } else { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* addition */ + /*----------------------------*/ + fprintf(outfile,"ADD (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + } + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* unary '-' */ + /*----------------------------*/ + case '-': /* can be unary */ + if (!tree->right) { + fprintf(outfile,"UMINUS (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + } else { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* subtraction */ + /*----------------------------*/ + fprintf(outfile,"SUB (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + } + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* compliment */ + /*----------------------------*/ + case '~': + fprintf(outfile,"COMPL (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* not */ + /*----------------------------*/ + case '!': + fprintf(outfile,"NOT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* shift */ + /*----------------------------*/ + case RRC: + fprintf(outfile,"RRC (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + + case RLC: + fprintf(outfile,"RLC (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + case GETHBIT: + fprintf(outfile,"GETHBIT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + return ; + case LEFT_OP: + fprintf(outfile,"LEFT_SHIFT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case RIGHT_OP: + fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* casting */ + /*----------------------------*/ + case CAST: /* change the type */ + fprintf(outfile,"CAST (%p) from type (",tree); + printTypeChain(tree->right->ftype,outfile); + fprintf(outfile,") to type ("); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->right,outfile,indent+4); + return ; + + case AND_OP: + fprintf(outfile,"ANDAND (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case OR_OP: + fprintf(outfile,"OROR (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* comparison operators */ + /*----------------------------*/ + case '>': + fprintf(outfile,"GT(>) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case '<': + fprintf(outfile,"LT(<) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case LE_OP: + fprintf(outfile,"LE(<=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case GE_OP: + fprintf(outfile,"GE(>=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case EQ_OP: + fprintf(outfile,"EQ(==) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + case NE_OP: + fprintf(outfile,"NE(!=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* sizeof */ + /*----------------------------*/ + case SIZEOF: /* evaluate wihout code generation */ + fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype))); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* conditional operator '?' */ + /*----------------------------*/ + case '?': + fprintf(outfile,"QUEST(?) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + + case ':': + fprintf(outfile,"COLON(:) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* assignment operators */ + /*----------------------------*/ + case MUL_ASSIGN: + fprintf(outfile,"MULASS(*=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case DIV_ASSIGN: + fprintf(outfile,"DIVASS(/=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case AND_ASSIGN: + fprintf(outfile,"ANDASS(&=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case OR_ASSIGN: + fprintf(outfile,"ORASS(*=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case XOR_ASSIGN: + fprintf(outfile,"XORASS(*=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case RIGHT_ASSIGN: + fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case LEFT_ASSIGN: + fprintf(outfile,"LSHFTASS(*=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* -= operator */ + /*----------------------------*/ + case SUB_ASSIGN: + fprintf(outfile,"SUBASS(-=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* += operator */ + /*----------------------------*/ + case ADD_ASSIGN: + fprintf(outfile,"ADDASS(+=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* straight assignemnt */ + /*----------------------------*/ + case '=': + fprintf(outfile,"ASSIGN(=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* comma operator */ + /*----------------------------*/ + case ',': + fprintf(outfile,"COMMA(,) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* function call */ + /*----------------------------*/ + case CALL: + case PCALL: + fprintf(outfile,"CALL (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent+4); + return; + case PARAM: + fprintf(outfile,"PARMS\n"); + ast_print(tree->left,outfile,indent+4); + if (tree->right && !IS_AST_PARAM(tree->right)) { + ast_print(tree->right,outfile,indent+4); + } + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* return statement */ + /*----------------------------*/ + case RETURN: + fprintf(outfile,"RETURN (%p) type (",tree); + printTypeChain(tree->right->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->right,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* label statement */ + /*----------------------------*/ + case LABEL : + fprintf(outfile,"LABEL (%p)",tree); + ast_print(tree->left,outfile,indent+4); + ast_print(tree->right,outfile,indent); + return; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* switch statement */ + /*----------------------------*/ + case SWITCH: + { + value *val; + fprintf(outfile,"SWITCH (%p) ",tree); + ast_print(tree->left,outfile,0); + for (val = tree->values.switchVals.swVals; val ; val = val->next) { + INDENT(indent+4,outfile); + fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n", + (int) floatFromVal(val), + tree->values.switchVals.swNum, + (int) floatFromVal(val)); + } + ast_print(tree->right,outfile,indent); + } + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* ifx Statement */ + /*----------------------------*/ + case IFX: + fprintf(outfile,"IF (%p) \n",tree); + ast_print(tree->left,outfile,indent+4); + if (tree->trueLabel) { + INDENT(indent,outfile); + fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name); + } + if (tree->falseLabel) { + INDENT(indent,outfile); + fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name); + } + ast_print(tree->right,outfile,indent+4); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* for Statement */ + /*----------------------------*/ + case FOR: + fprintf(outfile,"FOR (%p) \n",tree); + if (AST_FOR( tree, initExpr)) { + INDENT(indent+4,outfile); + fprintf(outfile,"INIT EXPR "); + ast_print(AST_FOR(tree, initExpr),outfile,indent+4); + } + if (AST_FOR( tree, condExpr)) { + INDENT(indent+4,outfile); + fprintf(outfile,"COND EXPR "); + ast_print(AST_FOR(tree, condExpr),outfile,indent+4); + } + if (AST_FOR( tree, loopExpr)) { + INDENT(indent+4,outfile); + fprintf(outfile,"LOOP EXPR "); + ast_print(AST_FOR(tree, loopExpr),outfile,indent+4); + } + fprintf(outfile,"FOR LOOP BODY \n"); + ast_print(tree->left,outfile,indent+4); + return ; + default: + return ; + } +} + +void PA(ast *t) +{ + ast_print(t,stdout,0); +}