X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCast.c;h=354a70b2e99e0dbed33c6c9ddf7594e1ebe3f3f2;hb=c34cf61917860a821a4631edda334443633805e7;hp=bf5b3abf36243ddc146f058dd0d69153c074adb7;hpb=7489be486a8008b25b31654823bd7ac115d7ad85;p=fw%2Fsdcc diff --git a/src/SDCCast.c b/src/SDCCast.c index bf5b3abf..354a70b2 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -47,10 +47,12 @@ int labelKey = 1; int noLineno = 0; int noAlloc = 0; -symbol *currFunc; -ast *createIval (ast *, sym_link *, initList *, ast *); -ast *createIvalCharPtr (ast *, sym_link *, ast *); +symbol *currFunc=NULL; +static ast *createIval (ast *, sym_link *, initList *, ast *); +static ast *createIvalCharPtr (ast *, sym_link *, ast *); +static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); +ast *optimizeSWAP (ast *); ast *optimizeGetHbit (ast *); ast *backPatchLabels (ast *, symbol *, symbol *); void PA(ast *t); @@ -66,44 +68,8 @@ ptt (ast * tree) /*-----------------------------------------------------------------*/ -/* newAst - creates a fresh node for an expression tree */ +/* newAst - creates a fresh node for an expression tree */ /*-----------------------------------------------------------------*/ -#if 0 -ast * -newAst (int type, void *op) -{ - 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) { @@ -113,7 +79,7 @@ newAst_ (unsigned type) ex = Safe_alloc ( sizeof (ast)); ex->type = type; - ex->lineno = (noLineno ? oldLineno : yylineno); + ex->lineno = (noLineno ? oldLineno : mylineno); ex->filename = currFname; ex->level = NestLevel; ex->block = currBlockno; @@ -145,14 +111,6 @@ newAst_LINK (sym_link * val) return ex; } -ast * -newAst_STMNT (unsigned val) -{ - ast *ex = newAst_ (EX_STMNT); - ex->opval.stmnt = val; - return ex; -} - /*-----------------------------------------------------------------*/ /* newNode - creates a new node */ /*-----------------------------------------------------------------*/ @@ -202,7 +160,7 @@ newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel) /*-----------------------------------------------------------------*/ /* copyAstValues - copies value portion of ast if needed */ /*-----------------------------------------------------------------*/ -void +void copyAstValues (ast * dest, ast * src) { switch (src->opval.op) @@ -221,14 +179,13 @@ copyAstValues (ast * dest, ast * src) break; case INLINEASM: - dest->values.inlineasm = Safe_alloc (strlen (src->values.inlineasm) + 1); - strcpy (dest->values.inlineasm, src->values.inlineasm); + dest->values.inlineasm = Safe_strdup(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)); @@ -291,10 +248,35 @@ exit: } +/*-----------------------------------------------------------------*/ +/* removeIncDecOps: remove for side effects in *_ASSIGN's */ +/* "*s++ += 3" -> "*s++ = *s++ + 3" */ +/*-----------------------------------------------------------------*/ +ast *removeIncDecOps (ast * tree) { + + // traverse the tree and remove inc/dec ops + + if (!tree) + return NULL; + + if (tree->type == EX_OP && + (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) { + if (tree->left) + tree=tree->left; + else + tree=tree->right; + } + + tree->left=removeIncDecOps(tree->left); + tree->right=removeIncDecOps(tree->right); + + return tree; +} + /*-----------------------------------------------------------------*/ /* hasSEFcalls - returns TRUE if tree has a function call */ /*-----------------------------------------------------------------*/ -bool +bool hasSEFcalls (ast * tree) { if (!tree) @@ -377,6 +359,7 @@ resolveSymbols (ast * tree) if (tree == NULL) return tree; +#if 0 /* print the line */ /* if not block & function */ if (tree->type == EX_OP && @@ -387,6 +370,7 @@ resolveSymbols (ast * tree) filename = tree->filename; lineno = tree->lineno; } +#endif /* make sure we resolve the true & false labels for ifx */ if (tree->type == EX_OP && tree->opval.op == IFX) @@ -457,7 +441,7 @@ resolveSymbols (ast * tree) /* mark it as returning an int */ if (tree->funcName) { - tree->opval.val->sym->type = newLink (); + tree->opval.val->sym->type = newLink (DECLARATOR); DCL_TYPE (tree->opval.val->sym->type) = FUNCTION; tree->opval.val->sym->type->next = tree->opval.val->sym->etype = newIntLink (); @@ -487,8 +471,7 @@ resolveChildren: /*-----------------------------------------------------------------*/ /* 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; @@ -499,38 +482,6 @@ setAstLineno (ast * tree, int lineno) return 0; } -#if 0 -/* this functions seems to be superfluous?! kmh */ - -/*-----------------------------------------------------------------*/ -/* resolveFromTable - will return the symbal table value */ -/*-----------------------------------------------------------------*/ -value * -resolveFromTable (value * val) -{ - symbol *csym; - - 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; - } - - return val; -} -#endif - /*-----------------------------------------------------------------*/ /* funcOfType :- function of type with name */ /*-----------------------------------------------------------------*/ @@ -543,11 +494,11 @@ funcOfType (char *name, sym_link * type, sym_link * argType, sym = newSymbol (name, 0); /* setup return value */ - sym->type = newLink (); + sym->type = newLink (DECLARATOR); DCL_TYPE (sym->type) = FUNCTION; sym->type->next = copyLinkChain (type); sym->etype = getSpec (sym->type); - FUNC_ISREENT(sym->type) = rent; + FUNC_ISREENT(sym->type) = rent ? 1 : 0; /* if arguments required */ if (nArgs) @@ -587,7 +538,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) sym = newSymbol (name, 0); /* setup return value */ - sym->type = newLink (); + sym->type = newLink (DECLARATOR); DCL_TYPE (sym->type) = FUNCTION; sym->type->next = typeFromStr(rtype); sym->etype = getSpec (sym->type); @@ -605,7 +556,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) args = args->next = newValue (); } } - + /* save it */ addSymChain (sym); sym->cdef = 1; @@ -617,7 +568,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) /*-----------------------------------------------------------------*/ /* reverseParms - will reverse a parameter tree */ /*-----------------------------------------------------------------*/ -void +static void reverseParms (ast * ptree) { ast *ttree; @@ -708,19 +659,32 @@ processParms (ast * func, if (IS_INTEGRAL (ftype) && (getSize (ftype) < (unsigned) INTSIZE)) { - newType = newAst_LINK(INTTYPE); + if (IS_AST_OP(actParm) && + (actParm->opval.op == LEFT_OP || + actParm->opval.op == '*' || + actParm->opval.op == '+' || + actParm->opval.op == '-') && + actParm->right) { + // we should cast an operand instead of the result + actParm->decorated = 0; + actParm->left = newNode( CAST, newAst_LINK(newIntLink()), + actParm->left); + actParm = decorateType(actParm); + } else { + newType = newAst_LINK(INTTYPE); + } } if (IS_PTR(ftype) && !IS_GENPTR(ftype)) { newType = newAst_LINK (copyLinkChain(ftype)); - DCL_TYPE (newType->opval.lnk) = GPOINTER; + DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; } if (IS_AGGREGATE (ftype)) { newType = newAst_LINK (copyLinkChain (ftype)); - DCL_TYPE (newType->opval.lnk) = GPOINTER; + DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; } if (newType) { @@ -795,13 +759,14 @@ processParms (ast * func, /* 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); + SPEC_ARGREG (actParm->etype) = SPEC_ARGREG (defParm->etype); (*parmNumber)++; return 0; } /*-----------------------------------------------------------------*/ /* createIvalType - generates ival for basic types */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIvalType (ast * sym, sym_link * type, initList * ilist) { ast *iExpr; @@ -817,7 +782,7 @@ createIvalType (ast * sym, sym_link * type, initList * ilist) /*-----------------------------------------------------------------*/ /* createIvalStruct - generates initial value for structures */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIvalStruct (ast * sym, sym_link * type, initList * ilist) { ast *rast = NULL; @@ -857,7 +822,7 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) /*-----------------------------------------------------------------*/ /* createIvalArray - generates code for array initialization */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIvalArray (ast * sym, sym_link * type, initList * ilist) { ast *rast = NULL; @@ -952,7 +917,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) /*-----------------------------------------------------------------*/ /* createIvalCharPtr - generates initial values for char pointers */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) { ast *rast = NULL; @@ -992,6 +957,10 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) newNode ('[', sym, newAst_VALUE (valueFromLit ((float) i))), newAst_VALUE (valueFromLit (*s)))); + + // now WE don't need iexpr's symbol anymore + freeStringSymbol(AST_SYMBOL(iexpr)); + return decorateType (resolveSymbols (rast)); } @@ -1001,7 +970,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /*-----------------------------------------------------------------*/ /* createIvalPtr - generates initial value for pointers */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIvalPtr (ast * sym, sym_link * type, initList * ilist) { ast *rast; @@ -1024,7 +993,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) /*-----------------------------------------------------------------*/ /* createIval - generates code for initial value */ /*-----------------------------------------------------------------*/ -ast * +static ast * createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) { ast *rast = NULL; @@ -1047,7 +1016,7 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* if type is SPECIFIER */ if (IS_SPEC (type)) rast = createIvalType (sym, type, ilist); - + if (wid) return decorateType (resolveSymbols (newNode (NULLOP, wid, rast))); else @@ -1057,42 +1026,7 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /*-----------------------------------------------------------------*/ /* initAggregates - initialises aggregate variables with initv */ /*-----------------------------------------------------------------*/ - -/* 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); } @@ -1100,7 +1034,7 @@ ast * initAggregates (symbol * sym, initList * ival, ast * wid) { /* gatherAutoInit - creates assignment expressions for initial */ /* values */ /*-----------------------------------------------------------------*/ -ast * +static ast * gatherAutoInit (symbol * autoChain) { ast *init = NULL; @@ -1124,11 +1058,6 @@ gatherAutoInit (symbol * autoChain) { 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); @@ -1160,6 +1089,16 @@ gatherAutoInit (symbol * autoChain) /* if there is an initial value */ if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE) { + initList *ilist=sym->ival; + + while (ilist->type == INIT_DEEP) { + ilist = ilist->init.deep; + } + + /* update lineno for error msg */ + lineno=sym->lineDef; + setAstLineno (ilist->init.node, lineno); + if (IS_AGGREGATE (sym->type)) { work = initAggregates (sym, sym->ival, NULL); } else { @@ -1170,8 +1109,10 @@ gatherAutoInit (symbol * autoChain) work = newNode ('=', newAst_VALUE (symbolVal (sym)), list2expr (sym->ival)); } - + + // just to be sure setAstLineno (work, sym->lineDef); + sym->ival = NULL; if (init) init = newNode (NULLOP, init, work); @@ -1183,6 +1124,20 @@ gatherAutoInit (symbol * autoChain) return init; } +/*-----------------------------------------------------------------*/ +/* freeStringSymbol - delete a literal string if no more usage */ +/*-----------------------------------------------------------------*/ +void freeStringSymbol(symbol *sym) { + /* make sure this is a literal string */ + assert (sym->isstrlit); + if (--sym->isstrlit == 0) { // lower the usage count + memmap *segment=SPEC_OCLS(sym->etype); + if (segment) { + deleteSetItem(&segment->syms, sym); + } + } +} + /*-----------------------------------------------------------------*/ /* stringToSymbol - creates a symbol from a literal string */ /*-----------------------------------------------------------------*/ @@ -1192,10 +1147,22 @@ stringToSymbol (value * val) char name[SDCC_NAME_MAX + 1]; static int charLbl = 0; symbol *sym; + set *sp; + + // have we heard this before? + for (sp=statsg->syms; sp; sp=sp->next) { + sym=sp->item; + if (sym->isstrlit && + !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) { + // yes, this is old news. Don't publish it again. + sym->isstrlit++; // but raise the usage count + return symbolVal(sym); + } + } - sprintf (name, "_str_%d", charLbl++); + SNPRINTF (name, sizeof(name), "_str_%d", charLbl++); sym = newSymbol (name, 0); /* make it @ level 0 */ - strcpy (sym->rname, name); + strncpyz (sym->rname, name, SDCC_NAME_MAX); /* copy the type from the value passed */ sym->type = copyLinkChain (val->type); @@ -1237,14 +1204,14 @@ processBlockVars (ast * tree, int *stack, int action) 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); } @@ -1254,6 +1221,74 @@ processBlockVars (ast * tree, int *stack, int action) return tree; } + +/*-------------------------------------------------------------*/ +/* constExprTree - returns TRUE if this tree is a constant */ +/* expression */ +/*-------------------------------------------------------------*/ +bool constExprTree (ast *cexpr) { + + if (!cexpr) { + return TRUE; + } + + cexpr = decorateType (resolveSymbols (cexpr)); + + switch (cexpr->type) + { + case EX_VALUE: + if (IS_AST_LIT_VALUE(cexpr)) { + // this is a literal + return TRUE; + } + if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) { + // a function's address will never change + return TRUE; + } + if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) { + // an array's address will never change + return TRUE; + } + if (IS_AST_SYM_VALUE(cexpr) && + IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) { + // a symbol in code space will never change + // This is only for the 'char *s="hallo"' case and will have to leave + //printf(" code space symbol"); + return TRUE; + } + return FALSE; + case EX_LINK: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unexpected link in expression tree\n"); + return FALSE; + case EX_OP: + if (cexpr->opval.op==ARRAYINIT) { + // this is a list of literals + return TRUE; + } + if (cexpr->opval.op=='=') { + return constExprTree(cexpr->right); + } + if (cexpr->opval.op==CAST) { + // cast ignored, maybe we should throw a warning here? + return constExprTree(cexpr->right); + } + if (cexpr->opval.op=='&') { + return TRUE; + } + if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) { + return FALSE; + } + if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) { + return TRUE; + } + return FALSE; + case EX_OPERAND: + return IS_CONSTANT(operandType(cexpr->opval.oprnd)); + } + return FALSE; +} + /*-----------------------------------------------------------------*/ /* constExprValue - returns the value of a constant expression */ /* or NULL if it is not a constant expression */ @@ -1277,19 +1312,23 @@ constExprValue (ast * cexpr, int check) 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); + strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX); return val; } /* if we are casting a literal value then */ if (IS_AST_OP (cexpr) && cexpr->opval.op == CAST && - IS_LITERAL (cexpr->left->ftype)) + IS_LITERAL (cexpr->right->ftype)) + { return valCastLiteral (cexpr->ftype, - floatFromVal (cexpr->left->opval.val)); + floatFromVal (cexpr->right->opval.val)); + } if (IS_AST_VALUE (cexpr)) + { return cexpr->opval.val; + } if (check) werror (E_CONST_EXPECTED, "found expression"); @@ -1535,8 +1574,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /* 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; @@ -1547,6 +1585,10 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) { /*------------------------------------------------------------------*/ case '[': + // if the loopvar is used as an index + if (astHasSymbol(pbody->right, sym)) { + return FALSE; + } return isConformingBody (pbody->right, sym, body); /*------------------------------------------------------------------*/ @@ -1555,7 +1597,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) return TRUE; /*------------------------------------------------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: case DEC_OP: /* sure we are not sym is not modified */ @@ -1623,6 +1665,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case RRC: case RLC: case GETHBIT: + case SWAP: if (IS_AST_SYM_VALUE (pbody->left) && isSymbolEqual (AST_SYMBOL (pbody->left), sym)) return FALSE; @@ -1641,6 +1684,14 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case '?': case ':': case SIZEOF: /* evaluate wihout code generation */ + + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + + if (IS_AST_SYM_VALUE (pbody->right) && + isSymbolEqual (AST_SYMBOL (pbody->right), sym)) + return FALSE; return isConformingBody (pbody->left, sym, body) && isConformingBody (pbody->right, sym, body); @@ -1656,9 +1707,16 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) if (astHasVolatile (pbody->left)) return FALSE; - if (IS_AST_SYM_VALUE (pbody->left) && - isSymbolEqual (AST_SYMBOL (pbody->left), sym)) - return FALSE; + if (IS_AST_SYM_VALUE (pbody->left)) { + // if the loopvar has an assignment + if (isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + // if the loopvar is used in another (maybe conditional) block + if (astHasSymbol (pbody->right, sym) && + (pbody->level >= body->level)) { + return FALSE; + } + } if (astHasVolatile (pbody->left)) return FALSE; @@ -1692,6 +1750,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /* function call */ /*----------------------------*/ case CALL: + /* if local & not passed as paramater then ok */ + if (sym->level && !astHasSymbol(pbody->right,sym)) + return TRUE; return FALSE; /*------------------------------------------------------------------*/ @@ -1726,7 +1787,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /* if the for loop is reversible. If yes will set the value of */ /* the loop control var & init value & termination value */ /*-----------------------------------------------------------------*/ -bool +bool isLoopReversible (ast * loop, symbol ** loopCntrl, ast ** init, ast ** end) { @@ -1805,13 +1866,14 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) rloop = newNode (NULLOP, createIf (newAst_VALUE (symbolVal (sym)), newNode (GOTO, - newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))), + newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))), NULL), NULL), newNode ('=', newAst_VALUE (symbolVal (sym)), end)); replLoopSym (loop->left, sym); + setAstLineno (rloop, init->lineno); rloop = newNode (NULLOP, newNode ('=', @@ -1822,58 +1884,66 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) loop->left, newNode (NULLOP, newNode (SUB_ASSIGN, - newAst_VALUE (symbolVal (sym)), - newAst_VALUE (constVal ("1"))), + newAst_VALUE (symbolVal (sym)), + newAst_VALUE (constVal ("1"))), rloop)))); + rloop->lineno=init->lineno; return decorateType (rloop); } -//#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. */ +/* searchLitOp - search tree (*ops only) for an ast with literal */ /*-----------------------------------------------------------------*/ -void -pushTypeCastToLeaves (sym_link * type, ast * node, ast ** parentPtr) +static ast * +searchLitOp (ast *tree, ast **parent, const char *ops) { - if (!node || IS_CALLOP(node)) - { - /* WTF? We should never get here. */ - return; - } + ast *ret; - 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)); - } - } - else + if (tree && optimize.global_cse) { - if (node->left) + /* is there a literal operand? */ + if (tree->right && + IS_AST_OP(tree->right) && + tree->right->right && + (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1])) { - pushTypeCastToLeaves (type, node->left, &(node->left)); - } - if (node->right) + if (IS_LITERAL (RTYPE (tree->right)) ^ + IS_LITERAL (LTYPE (tree->right))) + { + tree->right->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->right; + } + ret = searchLitOp (tree->right, parent, ops); + if (ret) + return ret; + } + if (tree->left && + IS_AST_OP(tree->left) && + tree->left->right && + (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1])) { - pushTypeCastToLeaves (type, node->right, &(node->right)); + if (IS_LITERAL (RTYPE (tree->left)) ^ + IS_LITERAL (LTYPE (tree->left))) + { + tree->left->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->left; + } + ret = searchLitOp (tree->left, parent, ops); + if (ret) + return ret; } } + return NULL; } -#endif - /*-----------------------------------------------------------------*/ -/* decorateType - compute type for this tree also does type cheking */ +/* decorateType - compute type for this tree also does type checking */ /* this is done bottom up, since type have to flow upwards */ /* it also does constant folding, and paramater checking */ /*-----------------------------------------------------------------*/ @@ -1892,6 +1962,7 @@ decorateType (ast * tree) tree->decorated = 1; +#if 0 /* print the line */ /* if not block & function */ if (tree->type == EX_OP && @@ -1902,6 +1973,7 @@ decorateType (ast * tree) filename = tree->filename; lineno = tree->lineno; } +#endif /* if any child is an error | this one is an error do nothing */ if (tree->isError || @@ -1913,6 +1985,7 @@ decorateType (ast * tree) /*----------------------------*/ /* leaf has been reached */ /*----------------------------*/ + lineno=tree->lineno; /* if this is of type value */ /* just get the type */ if (tree->type == EX_VALUE) @@ -1975,7 +2048,9 @@ decorateType (ast * tree) ast *dtl, *dtr; dtl = decorateType (tree->left); - dtr = decorateType (tree->right); + /* delay right side for '?' operator since conditional macro expansions might + rely on this */ + dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right)); /* this is to take care of situations when the tree gets rewritten */ @@ -1983,16 +2058,38 @@ decorateType (ast * tree) tree->left = dtl; if (dtr != tree->right) tree->right = dtr; + if ((dtl && dtl->isError) || (dtr && dtr->isError)) + return tree; + + if (IS_AST_OP(tree) && + (tree->opval.op == CAST || tree->opval.op == '=') && + (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) && + (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) { + // this is a cast/assign to a bigger type + if (IS_AST_OP(tree->right) && + IS_INTEGRAL(tree->right->ftype) && + (tree->right->opval.op == LEFT_OP || + tree->right->opval.op == '*' || + tree->right->opval.op == '+' || + tree->right->opval.op == '-') && + tree->right->right) { + // we should cast an operand instead of the result + tree->right->decorated = 0; + tree->right->left = newNode( CAST, newAst_LINK(newIntLink()), + tree->right->left); + tree->right = decorateType(tree->right); + } + } } /* depending on type of operator do */ switch (tree->opval.op) { - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* array node */ - /*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* array node */ + /*----------------------------*/ case '[': /* determine which is the array & which the index */ @@ -2026,9 +2123,6 @@ decorateType (ast * tree) } 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; /*------------------------------------------------------------------*/ @@ -2054,7 +2148,7 @@ decorateType (ast * tree) /*----------------------------*/ case PTR_OP: /* if not pointer to a structure */ - if (!IS_PTR (LTYPE (tree))) + if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree))) { werror (E_PTR_REQD); goto errorTreeReturn; @@ -2070,19 +2164,84 @@ decorateType (ast * tree) (tree->right->type == EX_VALUE ? tree->right->opval.val : NULL)); TETYPE (tree) = getSpec (TTYPE (tree)); + + /* adjust the storage class */ + switch (DCL_TYPE(tree->left->ftype)) { + case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; + break; + case FPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XDATA; + break; + case CPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_CODE; + break; + case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case PPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + break; + case IPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_IDATA; + break; + case EEPPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_EEPROM; + break; + case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case ARRAY: + case FUNCTION: + break; + } + + if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left) + && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype)) + { + /* If defined struct type at addr var + then rewrite (&struct var)->member + as temp + and define membertype at (addr+offsetof(struct var,member)) temp + */ + symbol *sym; + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)), + AST_SYMBOL(tree->right)); + + sym = newSymbol(genSymName (0), 0); + sym->type = TTYPE (tree); + sym->etype = getSpec(sym->type); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype) + + element->offset; + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + AST_VALUE (tree) = symbolVal(sym); + TLVAL (tree) = 1; + TRVAL (tree) = 0; + tree->type = EX_VALUE; + tree->left = NULL; + tree->right = NULL; + } + return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* ++/-- operation */ -/*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + /*----------------------------*/ + case INC_OP: case DEC_OP: { sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree)); COPYTYPE (TTYPE (tree), TETYPE (tree), ltc); - if (!tree->initMode && IS_CONSTANT(TETYPE(tree))) - werror (E_CODE_WRITE, "++/--"); + if (!tree->initMode && IS_CONSTANT(TTYPE(tree))) + werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--"); if (tree->right) RLVAL (tree) = 1; @@ -2091,10 +2250,10 @@ decorateType (ast * tree) return tree; } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* bitwise and */ -/*----------------------------*/ + /*----------------------------*/ case '&': /* can be unary */ /* if right is NULL then unary operation */ if (tree->right) /* not an unary operation */ @@ -2137,16 +2296,40 @@ decorateType (ast * tree) computeType (LTYPE (tree), RTYPE (tree)); TETYPE (tree) = getSpec (TTYPE (tree)); + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a and-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "&"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; return tree; } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* address of */ -/*----------------------------*/ - p = newLink (); - p->class = DECLARATOR; + /*----------------------------*/ + p = newLink (DECLARATOR); /* if bit field then error */ if (IS_BITVAR (tree->left->etype)) { @@ -2162,8 +2345,8 @@ decorateType (ast * tree) if (IS_FUNC (LTYPE (tree))) { - werror (E_ILLEGAL_ADDR, "address of function"); - goto errorTreeReturn; + // this ought to be ignored + return (tree->left); } if (IS_LITERAL(LTYPE(tree))) @@ -2178,10 +2361,7 @@ decorateType (ast * tree) goto errorTreeReturn; } if (SPEC_SCLS (tree->left->etype) == S_CODE) - { - DCL_TYPE (p) = CPOINTER; - DCL_PTR_CONST (p) = port->mem.code_ro; - } + DCL_TYPE (p) = CPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XDATA) DCL_TYPE (p) = FPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XSTACK) @@ -2204,27 +2384,72 @@ decorateType (ast * tree) p->next = LTYPE (tree); TTYPE (tree) = p; TETYPE (tree) = getSpec (TTYPE (tree)); - DCL_PTR_CONST (p) = SPEC_CONST (TETYPE (tree)); - DCL_PTR_VOLATILE (p) = SPEC_VOLATILE (TETYPE (tree)); LLVAL (tree) = 1; TLVAL (tree) = 1; + + #if 0 + if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP + && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left)) + { + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)), + AST_SYMBOL(tree->left->right)); + AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left), + valueFromLit(element->offset)); + tree->left = NULL; + tree->right = NULL; + tree->type = EX_VALUE; + tree->values.literalFromCast = 1; + } + #endif + return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* bitwise or */ -/*----------------------------*/ + /*----------------------------*/ case '|': /* if the rewrite succeeds then don't go any furthur */ { ast *wtree = optimizeRRCRLC (tree); if (wtree != tree) return decorateType (wtree); + + wtree = optimizeSWAP (tree); + if (wtree != tree) + return decorateType (wtree); + + // fall through } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a or-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "|"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent); + } + } + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* bitwise xor */ -/*----------------------------*/ + /*----------------------------*/ case '^': if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { @@ -2250,15 +2475,41 @@ decorateType (ast * tree) TTYPE (tree) = tree->opval.val->type; return tree; } + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a xor-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "^"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent); + } + } + 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))) { @@ -2277,16 +2528,49 @@ decorateType (ast * tree) tree->opval.val->type); return tree; } + LRVAL (tree) = RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree))); + + /* if right is a literal and */ + /* left is also a division by a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "/"); + if (litTree) + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_div */ + litTree->right = newNode ('*', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("1"); + decorateType (parent); + } + else + { + /* litTree->left is literal: no gcse possible. + We can't call decorateType(parent), because + this would cause an infinit loop. */ + parent->decorated = 1; + decorateType (litTree); + } + } + } + return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* modulus */ -/*----------------------------*/ + /*----------------------------*/ case '%': if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { @@ -2316,10 +2600,10 @@ decorateType (ast * tree) RTYPE (tree))); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ -/* address dereference */ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* address dereference */ + /*----------------------------*/ case '*': /* can be unary : if right is null then unary operation */ if (!tree->right) { @@ -2334,17 +2618,50 @@ decorateType (ast * 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)); - SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); + if (IS_ADDRESS_OF_OP(tree->left)) + { + /* replace *&obj with obj */ + return tree->left->left; + } + TTYPE (tree) = copyLinkChain (LTYPE (tree)->next); + TETYPE (tree) = getSpec (TTYPE (tree)); + /* adjust the storage class */ + switch (DCL_TYPE(tree->left->ftype)) { + case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; + break; + case FPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XDATA; + break; + case CPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_CODE; + break; + case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case PPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + break; + case IPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_IDATA; + break; + case EEPPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_EEPROM; + break; + case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case ARRAY: + case FUNCTION: + break; + } return tree; } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* multiplication */ -/*----------------------------*/ + /*----------------------------*/ if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) { werror (E_INVALID_OP, "multiplication"); @@ -2372,25 +2689,40 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* we can find a 2nd literal in a mul-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "*"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree))); + /* promote result to int if left & right are char this will facilitate hardware multiplies 8bit x 8bit = 16bit */ if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) { - 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) @@ -2415,10 +2747,10 @@ decorateType (ast * tree) return tree; } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* addition */ -/*----------------------------*/ + /*----------------------------*/ /* this is not a unary operation */ /* if both pointers then problem */ @@ -2466,9 +2798,49 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *litTree, *parent; + litTree = searchLitOp (tree, &parent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_aa */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tree->left; + tree->left = tTree; + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_asr */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + } + else + { + /* foo_asl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + litTree->opval.op = '+'; + tree->opval.op = '-'; + } + } + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; /* if the left is a pointer */ - if (IS_PTR (LTYPE (tree))) + if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) ) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); else @@ -2477,10 +2849,10 @@ decorateType (ast * tree) RTYPE (tree))); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* unary '-' */ -/*----------------------------*/ + /*----------------------------*/ case '-': /* can be unary */ /* if right is null then unary */ if (!tree->right) @@ -2503,14 +2875,14 @@ decorateType (ast * tree) return tree; } LRVAL (tree) = 1; - TTYPE (tree) = LTYPE (tree); + TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree)); return tree; } -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* subtraction */ -/*----------------------------*/ + /*----------------------------*/ if (!(IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)) || @@ -2574,13 +2946,55 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree))); + LRVAL (tree) = RRVAL (tree) = 1; + + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0) + { + ast *litTree, *litParent; + litTree = searchLitOp (tree, &litParent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_sa */ + litTree->right = newNode ('-', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_ssr */ + litTree->right = newNode ('+', tree->right, litTree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else + { + /* foo_ssl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + } + } + decorateType (litParent); + } + } return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ - /* compliment */ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* complement */ + /*----------------------------*/ case '~': /* can be only integral type */ if (!IS_INTEGRAL (LTYPE (tree))) @@ -2602,10 +3016,10 @@ decorateType (ast * tree) COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* not */ -/*----------------------------*/ + /*----------------------------*/ case '!': /* can be pointer */ if (!IS_ARITHMETIC (LTYPE (tree)) && @@ -2629,12 +3043,13 @@ decorateType (ast * tree) TTYPE (tree) = TETYPE (tree) = newCharLink (); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* shift */ -/*----------------------------*/ + /*----------------------------*/ case RRC: case RLC: + case SWAP: TTYPE (tree) = LTYPE (tree); TETYPE (tree) = LETYPE (tree); return tree; @@ -2669,29 +3084,29 @@ decorateType (ast * 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)) && ((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; + if (tree->opval.op==LEFT_OP || + (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) { + lineno=tree->lineno; + werror (W_SHIFT_CHANGED, + (tree->opval.op == LEFT_OP ? "left" : "right")); + tree->type = EX_VALUE; + tree->left = tree->right = NULL; + tree->opval.val = constVal ("0"); + TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; + return tree; + } } 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)); - } + TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree)); + if (IS_LITERAL (TTYPE (tree))) + SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL; return tree; /*------------------------------------------------------------------*/ @@ -2705,7 +3120,7 @@ decorateType (ast * tree) werror (E_CAST_ILLEGAL); goto errorTreeReturn; } - + /* make sure the type is complete and sane */ checkTypeSanity(LETYPE(tree), "(cast)"); @@ -2721,11 +3136,11 @@ decorateType (ast * tree) tree->right = NULL; TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && + } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ { sym_link *rest = LTYPE(tree)->next; - werror(W_LITERAL_GENERIC); - TTYPE(tree) = newLink(); + werror(W_LITERAL_GENERIC); + TTYPE(tree) = newLink(DECLARATOR); DCL_TYPE(TTYPE(tree)) = FPOINTER; TTYPE(tree)->next = rest; tree->left->opval.lnk = TTYPE(tree); @@ -2739,35 +3154,127 @@ decorateType (ast * tree) LRVAL (tree) = 1; } #else +#if 0 // this is already checked, now this could be explicit /* 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; + strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) + { + werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag, + SPEC_STRUCT(LETYPE(tree))->tag); + } +#endif + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_SYM_VALUE (tree->right->left) + && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) { + + tree->type = EX_VALUE; tree->opval.val = valCastLiteral (LTYPE (tree), - floatFromVal (valFromType (RETYPE (tree)))); + SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype)); + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); tree->left = NULL; tree->right = NULL; - TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else { - TTYPE (tree) = LTYPE (tree); - LRVAL (tree) = 1; + return tree; + } + + /* handle offsetof macro: */ + /* #define offsetof(TYPE, MEMBER) \ */ + /* ((unsigned) &((TYPE *)0)->MEMBER) */ + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_OP (tree->right->left) + && tree->right->left->opval.op == PTR_OP + && IS_AST_OP (tree->right->left->left) + && tree->right->left->left->opval.op == CAST + && IS_AST_LIT_VALUE(tree->right->left->left->right)) { + + symbol *element = getStructElement ( + SPEC_STRUCT (LETYPE(tree->right->left)), + AST_SYMBOL(tree->right->left->right) + ); + + if (element) { + tree->type = EX_VALUE; + tree->opval.val = valCastLiteral ( + LTYPE (tree), + element->offset + + floatFromVal (valFromType (RETYPE (tree->right->left->left))) + ); + + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); + tree->left = NULL; + tree->right = NULL; + return tree; + } + } + + /* if the right is a literal replace the tree */ + if (IS_LITERAL (RETYPE (tree))) { + if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) { + /* rewrite (type *)litaddr + as &temp + and define type at litaddr temp + (but only if type's storage class is not generic) + */ + ast *newTree = newNode ('&', NULL, NULL); + symbol *sym; + + TTYPE (newTree) = LTYPE (tree); + TETYPE (newTree) = getSpec(LTYPE (tree)); + + /* define a global symbol at the casted address*/ + sym = newSymbol(genSymName (0), 0); + sym->type = LTYPE (tree)->next; + if (!sym->type) + sym->type = newLink (V_VOID); + sym->etype = getSpec(sym->type); + SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree)); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree))); + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + newTree->left = newAst_VALUE(symbolVal(sym)); + newTree->left->lineno = tree->lineno; + LTYPE (newTree) = sym->type; + LETYPE (newTree) = sym->etype; + LLVAL (newTree) = 1; + LRVAL (newTree) = 0; + TLVAL (newTree) = 1; + return newTree; + } + if (!IS_PTR (LTYPE (tree))) { + tree->type = EX_VALUE; + tree->opval.val = + valCastLiteral (LTYPE (tree), + floatFromVal (valFromType (RETYPE (tree)))); + TTYPE (tree) = tree->opval.val->type; + tree->left = NULL; + tree->right = NULL; + tree->values.literalFromCast = 1; + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + } } -#endif + 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 */ @@ -2804,10 +3311,10 @@ decorateType (ast * tree) TTYPE (tree) = TETYPE (tree) = newCharLink (); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* comparison operators */ -/*----------------------------*/ + /*----------------------------*/ case '>': case '<': case LE_OP: @@ -2824,10 +3331,17 @@ decorateType (ast * tree) /* if they are pointers they must be castable */ if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) { + if (tree->opval.op==EQ_OP && + !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) { + // we cannot cast a gptr to a !gptr: switch the leaves + struct ast *s=tree->left; + tree->left=tree->right; + tree->right=s; + } if (compareType (LTYPE (tree), RTYPE (tree)) == 0) { werror (E_COMPARE_OP); - fprintf (stderr, "comparing type "); + fprintf (stderr, "comparring type "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, "to type "); printTypeChain (RTYPE (tree), stderr); @@ -2852,7 +3366,18 @@ decorateType (ast * tree) goto errorTreeReturn; } } + /* if unsigned value < 0 then always false */ + /* if (unsigned value) > 0 then (unsigned value) */ + if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) && + ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) { + if (tree->opval.op == '<') { + return tree->right; + } + if (tree->opval.op == '>') { + return tree->left; + } + } /* if they are both literal then */ /* rewrite the tree */ if (IS_LITERAL (RTYPE (tree)) && @@ -2871,20 +3396,96 @@ decorateType (ast * tree) 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))); + SNPRINTF(buffer, sizeof(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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* typeof */ + /*----------------------------*/ + case TYPEOF: + /* return typeof enum value */ + tree->type = EX_VALUE; + { + int typeofv = 0; + if (IS_SPEC(tree->right->ftype)) { + switch (SPEC_NOUN(tree->right->ftype)) { + case V_INT: + if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG; + else typeofv = TYPEOF_INT; + break; + case V_FLOAT: + typeofv = TYPEOF_FLOAT; + break; + case V_CHAR: + typeofv = TYPEOF_CHAR; + break; + case V_VOID: + typeofv = TYPEOF_VOID; + break; + case V_STRUCT: + typeofv = TYPEOF_STRUCT; + break; + case V_BITFIELD: + typeofv = TYPEOF_BITFIELD; + break; + case V_BIT: + typeofv = TYPEOF_BIT; + break; + case V_SBIT: + typeofv = TYPEOF_SBIT; + break; + default: + break; + } + } else { + switch (DCL_TYPE(tree->right->ftype)) { + case POINTER: + typeofv = TYPEOF_POINTER; + break; + case FPOINTER: + typeofv = TYPEOF_FPOINTER; + break; + case CPOINTER: + typeofv = TYPEOF_CPOINTER; + break; + case GPOINTER: + typeofv = TYPEOF_GPOINTER; + break; + case PPOINTER: + typeofv = TYPEOF_PPOINTER; + break; + case IPOINTER: + typeofv = TYPEOF_IPOINTER; + break; + case ARRAY: + typeofv = TYPEOF_ARRAY; + break; + case FUNCTION: + typeofv = TYPEOF_FUNCTION; + break; + default: + break; + } + } + SNPRINTF (buffer, sizeof(buffer), "%d", typeofv); + tree->opval.val = constVal (buffer); + tree->right = tree->left = NULL; + TETYPE (tree) = getSpec (TTYPE (tree) = + tree->opval.val->type); + } + return tree; /*------------------------------------------------------------------*/ /*----------------------------*/ /* conditional operator '?' */ @@ -2894,13 +3495,14 @@ decorateType (ast * tree) 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 (IS_LITERAL (LTYPE(tree))) { if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) { - return tree->right->left ; + return decorateType(tree->right->left) ; } else { - return tree->right->right ; + return decorateType(tree->right->right) ; } } else { + tree->right = decorateType(tree->right); TTYPE (tree) = RTYPE(tree); TETYPE (tree) = getSpec (TTYPE (tree)); } @@ -2919,10 +3521,11 @@ decorateType (ast * tree) return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ +#if 0 // assignment operators are converted by the parser + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* assignment operators */ -/*----------------------------*/ + /*----------------------------*/ case MUL_ASSIGN: case DIV_ASSIGN: /* for these it must be both must be integral */ @@ -2935,12 +3538,12 @@ decorateType (ast * 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 (LTYPE (tree))) + werror (E_CODE_WRITE, *tree->opval.op==MUL_ASSIGN ? "*=" : "/="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "*= or /="); + werror (E_LVALUE_REQUIRED, *tree->opval.op==MUL_ASSIGN ? "*=" : "/="); goto errorTreeReturn; } LLVAL (tree) = 1; @@ -2963,7 +3566,7 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, " "); + werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<="); if (LRVAL (tree)) { @@ -2974,10 +3577,10 @@ decorateType (ast * tree) return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* -= operator */ -/*----------------------------*/ + /*----------------------------*/ case SUB_ASSIGN: if (!(IS_PTR (LTYPE (tree)) || IS_ARITHMETIC (LTYPE (tree)))) @@ -2998,7 +3601,7 @@ decorateType (ast * tree) RTYPE (tree))); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, " "); + werror (E_CODE_WRITE, "-="); if (LRVAL (tree)) { @@ -3009,10 +3612,10 @@ decorateType (ast * tree) return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* += operator */ -/*----------------------------*/ + /*----------------------------*/ case ADD_ASSIGN: /* this is not a unary operation */ /* if both pointers then problem */ @@ -3039,7 +3642,7 @@ decorateType (ast * tree) RTYPE (tree))); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, " "); + werror (E_CODE_WRITE, "+="); if (LRVAL (tree)) { @@ -3051,11 +3654,12 @@ decorateType (ast * tree) tree->opval.op = '='; return tree; +#endif -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* straight assignemnt */ -/*----------------------------*/ + /*----------------------------*/ case '=': /* cannot be an aggregate */ if (IS_AGGREGATE (LTYPE (tree))) @@ -3068,13 +3672,7 @@ decorateType (ast * tree) 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; + printFromToType(RTYPE(tree),LTYPE(tree)); } /* if the left side of the tree is of type void @@ -3090,8 +3688,8 @@ decorateType (ast * tree) RRVAL (tree) = 1; LLVAL (tree) = 1; if (!tree->initMode ) { - if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree)))) - werror (E_CODE_WRITE, " "); + if (IS_CONSTANT(LTYPE(tree))) + werror (E_CODE_WRITE, "="); } if (LRVAL (tree)) { @@ -3101,18 +3699,18 @@ decorateType (ast * tree) return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* comma operator */ -/*----------------------------*/ + /*----------------------------*/ case ',': TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree)); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* function call */ -/*----------------------------*/ + /*----------------------------*/ case CALL: parmNumber = 1; @@ -3122,20 +3720,24 @@ decorateType (ast * tree) goto errorTreeReturn; } - if (options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) + if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && + !IFFUNC_ISBUILTIN(LTYPE(tree))) { - //FUNC_ARGS(tree->left->ftype) = - //reverseVal (FUNC_ARGS(tree->left->ftype)); reverseParms (tree->right); } - TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)->next); + if (IS_CODEPTR(LTYPE(tree))) { + TTYPE(tree) = LTYPE(tree)->next->next; + } else { + TTYPE(tree) = LTYPE(tree)->next; + } + TETYPE (tree) = getSpec (TTYPE (tree)); return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* return statement */ -/*----------------------------*/ + /*----------------------------*/ case RETURN: if (!tree->right) goto voidcheck; @@ -3171,17 +3773,17 @@ decorateType (ast * tree) if (!IS_VOID (currFunc->type->next) && tree->right == NULL) { - werror (E_VOID_FUNC, currFunc->name); + werror (W_VOID_FUNC, currFunc->name); goto errorTreeReturn; } TTYPE (tree) = TETYPE (tree) = NULL; return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* switch statement */ -/*----------------------------*/ + /*----------------------------*/ case SWITCH: /* the switch value must be an integer */ if (!IS_INTEGRAL (LTYPE (tree))) @@ -3193,10 +3795,10 @@ decorateType (ast * tree) TTYPE (tree) = TETYPE (tree) = NULL; return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* ifx Statement */ -/*----------------------------*/ + /*----------------------------*/ case IFX: tree->left = backPatchLabels (tree->left, tree->trueLabel, @@ -3204,10 +3806,10 @@ decorateType (ast * tree) TTYPE (tree) = TETYPE (tree) = NULL; return tree; -/*------------------------------------------------------------------*/ -/*----------------------------*/ + /*------------------------------------------------------------------*/ + /*----------------------------*/ /* for Statement */ -/*----------------------------*/ + /*----------------------------*/ case FOR: decorateType (resolveSymbols (AST_FOR (tree, initExpr))); @@ -3259,7 +3861,7 @@ sizeofOp (sym_link * type) checkTypeSanity(type, "(sizeof)"); /* get the size and convert it to character */ - sprintf (buff, "%d", getSize (type)); + SNPRINTF (buff, sizeof(buff), "%d", getSize (type)); /* now convert into value */ return constVal (buff); @@ -3293,7 +3895,7 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel) static int localLbl = 0; symbol *localLabel; - sprintf (buffer, "_and_%d", localLbl++); + SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++); localLabel = newSymbol (buffer, NestLevel); tree->left = backPatchLabels (tree->left, localLabel, falseLabel); @@ -3319,7 +3921,7 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel) static int localLbl = 0; symbol *localLabel; - sprintf (buffer, "_or_%d", localLbl++); + SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++); localLabel = newSymbol (buffer, NestLevel); tree->left = backPatchLabels (tree->left, trueLabel, localLabel); @@ -3381,12 +3983,12 @@ createBlock (symbol * decl, ast * body) ast *ex; /* if the block has nothing */ - if (!body) + if (!body && !decl) return NULL; ex = newNode (BLOCK, NULL, body); ex->values.sym = decl; - + ex->right = ex->right; ex->level++; ex->lineno = 0; @@ -3411,7 +4013,7 @@ createLabel (symbol * label, ast * stmnt) label = newSymbol (label->name, label->level); /* change the name before putting it in add _ */ - sprintf (name, "%s", label->name); + SNPRINTF(name, sizeof(name), "%s", label->name); /* put the label in the LabelSymbol table */ /* but first check if a label of the same */ @@ -3499,7 +4101,8 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) } /* create the case label */ - sprintf (caseLbl, "_case_%d_%d", + SNPRINTF(caseLbl, sizeof(caseLbl), + "_case_%d_%d", swStat->values.switchVals.swNum, (int) floatFromVal (caseVal->opval.val)); @@ -3528,7 +4131,8 @@ createDefault (ast * swStat, ast * stmnt) swStat->values.switchVals.swDefault = 1; /* create the label */ - sprintf (defLbl, "_default_%d", swStat->values.switchVals.swNum); + SNPRINTF (defLbl, sizeof(defLbl), + "_default_%d", swStat->values.switchVals.swNum); return createLabel (newSymbol (defLbl, 0), stmnt); } @@ -3551,18 +4155,18 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody) } /* create the labels */ - sprintf (buffer, "_iffalse_%d", Lblnum); + SNPRINTF (buffer, sizeof(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); + SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum); ifEnd = newSymbol (buffer, NestLevel); } - sprintf (buffer, "_iftrue_%d", Lblnum); + SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum); ifTrue = newSymbol (buffer, NestLevel); Lblnum++; @@ -3784,6 +4388,11 @@ optimizeGetHbit (ast * tree) if ((i = (int) AST_LIT_VALUE (tree->left->right)) != (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) return tree; + + /* make sure the port supports GETHBIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) + return tree; return decorateType (newNode (GETHBIT, tree->left->left, NULL)); @@ -3836,6 +4445,11 @@ optimizeRRCRLC (ast * root) (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext0; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); } @@ -3866,6 +4480,11 @@ tryNext0: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext1; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); @@ -3897,6 +4516,11 @@ tryNext1: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext2; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -3927,6 +4551,11 @@ tryNext2: (getSize (TTYPE (root->left->left)) * 8 - 1)) return root; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -3937,9 +4566,64 @@ tryNext2: } /*-----------------------------------------------------------------*/ -/* optimizeCompare - otimizes compares for bit variables */ +/* optimizeSWAP :- optimize for nibble/byte/word swaps */ /*-----------------------------------------------------------------*/ ast * +optimizeSWAP (ast * root) +{ + /* will look for trees of the form + (?expr << 4) | (?expr >> 4) or + (?expr >> 4) | (?expr << 4) will make that + into a SWAP : operation .. + note : by 4 I mean (number of bits required to hold the + variable /2 ) */ + /* if the root operations is not a | operation the not */ + if (!IS_BITOR (root)) + return root; + + /* (?expr << 4) | (?expr >> 4) */ + if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right)) + || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right))) + { + + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; + + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + return root; + + /* make sure it is the same expression */ + if (!isAstEqual (root->left->left, + root->right->left)) + return root; + + if (AST_LIT_VALUE (root->left->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + if (AST_LIT_VALUE (root->right->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + /* make sure the port supports SWAP */ + if (port->hasExtBitOp + && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left)))) + return root; + + /* found it : create the AST */ + return newNode (SWAP, root->left->left, NULL); + } + + + /* not found return root */ + return root; +} + +/*-----------------------------------------------------------------*/ +/* optimizeCompare - otimizes compares for bit variables */ +/*-----------------------------------------------------------------*/ +static ast * optimizeCompare (ast * root) { ast *optExpr = NULL; @@ -3986,63 +4670,6 @@ optimizeCompare (ast * root) vright = (root->right->type == EX_VALUE ? root->right->opval.val : NULL); - //#define EXPERIMENTAL -#ifdef EXPERIMENTAL - /* if left is unsigned and right is literal */ - if (vleft && vright && - IS_UNSIGNED(vleft->etype) && - IS_LITERAL(vright->etype)) { - double dval=floatFromVal(vright); - int op=root->opval.op; - - fprintf (stderr,"op: '"); - switch (op) { - case LE_OP: fprintf (stderr, "<= '"); break; - case EQ_OP: fprintf (stderr, "== '"); break; - case GE_OP: fprintf (stderr, ">= '"); break; - default: fprintf (stderr, "%c '", op); break; - } - fprintf (stderr, "%f\n", dval); - - switch (op) - { - case EQ_OP: - case LE_OP: - case '<': - if (dval<0 || (op=='<' && dval==0)) { - // unsigned is never < 0 - werror (W_IF_NEVER_TRUE); - optExpr = newAst_VALUE (constVal("0")); - return decorateType (optExpr); - } - if (dval==0) { - if (op==LE_OP) { - // change this into a cheaper EQ_OP - fprintf (stderr, "warning *** changed '<=' to '==' because of unsigned\n"); - root->opval.op=EQ_OP; - return root; - } - } - break; - case GE_OP: - case '>': - if (dval>0 || (op==GE_OP && dval==0)) { - // unsigned is never < 0 - werror (W_IF_ALWAYS_TRUE); - optExpr = newAst_VALUE (constVal("1")); - return decorateType (optExpr); - } - if (dval==0) { - if (op=='>') { - // change this into a cheaper reversed EQ_OP - fprintf (stderr, "warning *** changed '>' to '!=' because of unsigned\n"); - root->opval.op=EQ_OP; - } - } - } - } -#endif - /* if left is a BITVAR in BITSPACE */ /* and right is a LITERAL then opt- */ /* imize else do nothing */ @@ -4214,13 +4841,9 @@ createFunction (symbol * name, ast * body) addSymChain (name); allocVariables (name); } - name->lastLine = yylineno; + name->lastLine = mylineno; 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; @@ -4255,7 +4878,7 @@ createFunction (symbol * name, ast * body) name->stack = SPEC_STAK (fetype) = stack; /* name needs to be mangled */ - sprintf (name->rname, "%s%s", port->fun_prefix, name->name); + SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name); body = resolveSymbols (body); /* resolve the symbols */ body = decorateType (body); /* propagateType & do semantic checks */ @@ -4297,6 +4920,7 @@ skipall: /* dealloc the block variables */ processBlockVars (body, &stack, DEALLOCATE); + outputDebugStackSymbols(); /* deallocate paramaters */ deallocParms (FUNC_ARGS(name->type)); @@ -4305,14 +4929,14 @@ skipall: /* we are done freeup memory & cleanup */ noLineno--; - labelKey = 1; + if (port->reset_labelKey) labelKey = 1; name->key = 0; FUNC_HASBODY(name->type) = 1; addSet (&operKeyReset, name); applyToSet (operKeyReset, resetParmKey); if (options.debug) - cdbStructBlock (1, cdbFile); + cdbStructBlock(1); cleanUpLevel (LabelTab, 0); cleanUpBlock (StructTab, 1); @@ -4324,14 +4948,14 @@ skipall: } -#define INDENT(x,f) { int i ; for (i=0;i < x; i++) fprintf(f," "); } +#define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); 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 */ @@ -4344,7 +4968,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"ERROR_NODE(%p)\n",tree); } - + /* print the line */ /* if not block & function */ if (tree->type == EX_OP && @@ -4352,13 +4976,13 @@ void ast_print (ast * tree, FILE *outfile, int indent) tree->opval.op != BLOCK && tree->opval.op != NULLOP)) { } - + if (tree->opval.op == FUNCTION) { int arg=0; value *args=FUNC_ARGS(tree->left->opval.val->type); - fprintf(outfile,"FUNCTION (%s=%p) type (", + fprintf(outfile,"FUNCTION (%s=%p) type (", tree->left->opval.val->name, tree); - printTypeChain (tree->ftype,outfile); + printTypeChain (tree->left->opval.val->type->next,outfile); fprintf(outfile,") args ("); do { if (arg) { @@ -4383,8 +5007,8 @@ void ast_print (ast * tree, FILE *outfile, int indent) decls->name, decls); printTypeChain(decls->type,outfile); fprintf(outfile,")\n"); - - decls = decls->next; + + decls = decls->next; } ast_print(tree->right,outfile,indent+2); INDENT(indent,outfile); @@ -4392,9 +5016,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) 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 ; } @@ -4408,11 +5030,14 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* just get the type */ if (tree->type == EX_VALUE) { - if (IS_LITERAL (tree->opval.val->etype)) { - fprintf(outfile,"CONSTANT (%p) value = %d, 0x%x, %g", tree, - (int) floatFromVal(tree->opval.val), - (int) floatFromVal(tree->opval.val), - floatFromVal(tree->opval.val)); + if (IS_LITERAL (tree->opval.val->etype)) { + fprintf(outfile,"CONSTANT (%p) value = ", tree); + if (SPEC_USIGN (tree->opval.val->etype)) + fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val)); + else + fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val)); + fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) floatFromVal(tree->opval.val), + floatFromVal(tree->opval.val)); } else if (tree->opval.val->sym) { /* if the undefined flag is set then give error message */ if (tree->opval.val->sym->undefined) { @@ -4443,7 +5068,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* depending on type of operator do */ - + switch (tree->opval.op) { /*------------------------------------------------------------------*/ /*----------------------------*/ @@ -4485,25 +5110,35 @@ void ast_print (ast * tree, FILE *outfile, int indent) /*----------------------------*/ /* ++/-- operation */ /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"INC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postincrement case */ + ast_print(tree->right,outfile,indent+2); /* preincrement case */ return ; case DEC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"DEC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postdecrement case */ + ast_print(tree->right,outfile,indent+2); /* predecrement case */ return ; /*------------------------------------------------------------------*/ /*----------------------------*/ /* bitwise and */ /*----------------------------*/ - case '&': + case '&': if (tree->right) { fprintf(outfile,"& (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -4539,7 +5174,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->left,outfile,indent+2); ast_print(tree->right,outfile,indent+2); return ; - + /*------------------------------------------------------------------*/ /*----------------------------*/ /* division */ @@ -4669,6 +5304,12 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); return ; + case SWAP: + fprintf(outfile,"SWAP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; case GETHBIT: fprintf(outfile,"GETHBIT (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -4816,14 +5457,14 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->right,outfile,indent+2); return; case OR_ASSIGN: - fprintf(outfile,"ORASS(*=) (%p) type (",tree); + fprintf(outfile,"ORASS(|=) (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); ast_print(tree->right,outfile,indent+2); return; case XOR_ASSIGN: - fprintf(outfile,"XORASS(*=) (%p) type (",tree); + fprintf(outfile,"XORASS(^=) (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); @@ -4837,7 +5478,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->right,outfile,indent+2); return; case LEFT_ASSIGN: - fprintf(outfile,"LSHFTASS(*=) (%p) type (",tree); + fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); @@ -4912,7 +5553,9 @@ void ast_print (ast * tree, FILE *outfile, int indent) /*----------------------------*/ case RETURN: fprintf(outfile,"RETURN (%p) type (",tree); - printTypeChain(tree->right->ftype,outfile); + if (tree->right) { + printTypeChain(tree->right->ftype,outfile); + } fprintf(outfile,")\n"); ast_print(tree->right,outfile,indent+2); return ; @@ -4952,15 +5595,23 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"IF (%p) \n",tree); ast_print(tree->left,outfile,indent+2); if (tree->trueLabel) { - INDENT(indent,outfile); + INDENT(indent+2,outfile); fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name); } if (tree->falseLabel) { - INDENT(indent,outfile); + INDENT(indent+2,outfile); fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name); } ast_print(tree->right,outfile,indent+2); return ; + /*----------------------------*/ + /* goto Statement */ + /*----------------------------*/ + case GOTO: + fprintf(outfile,"GOTO (%p) \n",tree); + ast_print(tree->left,outfile,indent+2); + fprintf(outfile,"\n"); + return ; /*------------------------------------------------------------------*/ /*----------------------------*/ /* for Statement */ @@ -4985,6 +5636,9 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"FOR LOOP BODY \n"); ast_print(tree->left,outfile,indent+2); return ; + case CRITICAL: + fprintf(outfile,"CRITICAL (%p) \n",tree); + ast_print(tree->left,outfile,indent+2); default: return ; }