X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCast.c;h=9c929bd9dc0f663d4a59fa4d765e8e9e235a35c7;hb=6cef00bbb8c0e1e640411cf2eb4f9ea5016c9f8f;hp=f872f88c25fcb58d6b34ce0c6a191e919c118639;hpb=de704f5b1dc658f63cd0280690aecba9ca72bd11;p=fw%2Fsdcc diff --git a/src/SDCCast.c b/src/SDCCast.c index f872f88c..9c929bd9 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -31,6 +31,11 @@ set *astList = NULL; set *operKeyReset = NULL; ast *staticAutos = NULL; int labelKey = 1; +static struct { + int count; /* number of inline functions inserted */ + symbol * retsym; /* variable for inlined function return value */ + symbol * retlab; /* label ending inlined function (virtual return) */ +} inlineState; #define LRVAL(x) x->left->rvalue #define RRVAL(x) x->right->rvalue @@ -50,18 +55,21 @@ int labelKey = 1; int noLineno = 0; int noAlloc = 0; symbol *currFunc=NULL; -static ast *createIval (ast *, sym_link *, initList *, ast *); -static ast *createIvalCharPtr (ast *, sym_link *, ast *); +static ast *createIval (ast *, sym_link *, initList *, ast *, ast *); +static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *); static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); ast *optimizeSWAP (ast *); -ast *optimizeGetHbit (ast *); -ast *backPatchLabels (ast *, symbol *, symbol *); +ast *optimizeGetHbit (ast *, RESULT_TYPE); +ast *optimizeGetAbit (ast *, RESULT_TYPE); +ast *optimizeGetByte (ast *, RESULT_TYPE); +ast *optimizeGetWord (ast *, RESULT_TYPE); +static 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 +struct dbuf_s *codeOutBuf; +int ptt (ast * tree) { printTypeChain (tree->ftype, stdout); @@ -81,8 +89,8 @@ newAst_ (unsigned type) ex = Safe_alloc ( sizeof (ast)); ex->type = type; - ex->lineno = (noLineno ? oldLineno : mylineno); - ex->filename = currFname; + ex->lineno = (noLineno ? oldLineno : lexLineno); + ex->filename = lexFilename; ex->level = NestLevel; ex->block = currBlockno; ex->initMode = inInitMode; @@ -251,7 +259,7 @@ exit: return dest; } - +#if 0 /*-----------------------------------------------------------------*/ /* removeIncDecOps: remove for side effects in *_ASSIGN's */ /* "*s++ += 3" -> "*s++ = *s++ + 3" */ @@ -322,9 +330,91 @@ ast *removePostIncDecOps (ast * tree) { return tree; } +#endif +/*-----------------------------------------------------------------*/ +/* replaceAstWithTemporary: Replace the AST pointed to by the arg */ +/* with a reference to a new temporary variable. Returns*/ +/* an AST which assigns the original value to the */ +/* temporary. */ +/*-----------------------------------------------------------------*/ +static ast *replaceAstWithTemporary(ast **treeptr) +{ + symbol *sym = newSymbol (genSymName(NestLevel), NestLevel ); + ast *tempvar; + + /* Tell gatherImplicitVariables() to automatically give the + symbol the correct type */ + sym->infertype = 1; + sym->type = NULL; + sym->etype = NULL; + + tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr); + *treeptr = newAst_VALUE(symbolVal(sym)); + + addSymChain(&sym); + + return tempvar; +} + +/*-----------------------------------------------------------------*/ +/* createRMW: Create a read-modify-write expression, using a */ +/* temporary variable if necessary to avoid duplicating */ +/* any side effects, for use in e.g. */ +/* foo()->count += 5; becomes */ +/* tmp = foo(); tmp->count = tmp->count + 5; */ +/*-----------------------------------------------------------------*/ +ast * createRMW (ast *target, unsigned op, ast *operand) +{ + ast *readval, *writeval; + ast *tempvar1 = NULL; + ast *tempvar2 = NULL; + ast *result; + + if (!target || !operand) { + return NULL; + } + + /* we need to create two copies of target: one to read from and + one to write to. but we need to do this without duplicating + any side effects that may be contained in the tree. */ + + if (IS_AST_OP(target)) { + /* if this is a dereference, put the referenced item in the temporary */ + if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) { + /* create a new temporary containing the item being dereferenced */ + if (hasSEFcalls(target->left)) + tempvar1 = replaceAstWithTemporary(&(target->left)); + } else if (target->opval.op == '[') { + /* Array access is similar, but we have to avoid side effects in + both values [WIML: Why not transform a[b] to *(a+b) in parser?] */ + if (hasSEFcalls(target->left)) + tempvar1 = replaceAstWithTemporary(&(target->left)); + if (hasSEFcalls(target->right)) + tempvar2 = replaceAstWithTemporary(&(target->right)); + } else { + /* we would have to handle '.', but it is not generated any more */ + wassertl(target->opval.op != '.', "obsolete opcode in tree"); + + /* no other kinds of ASTs are lvalues and can contain side effects */ + } + } + + readval = target; + writeval = copyAst(target); + + result = newNode('=', writeval, newNode(op, readval, operand)); + if (tempvar2) + result = newNode(',', tempvar2, result); + if (tempvar1) + result = newNode(',', tempvar1, result); + + return result; + +} /*-----------------------------------------------------------------*/ -/* hasSEFcalls - returns TRUE if tree has a function call */ +/* hasSEFcalls - returns TRUE if tree has a function call, */ +/* inc/decrement, or other side effect */ /*-----------------------------------------------------------------*/ bool hasSEFcalls (ast * tree) @@ -573,7 +663,7 @@ funcOfType (char *name, sym_link * type, sym_link * argType, } /* save it */ - addSymChain (sym); + addSymChain (&sym); sym->cdef = 1; allocVariables (sym); return sym; @@ -586,23 +676,23 @@ funcOfType (char *name, sym_link * type, sym_link * argType, symbol * funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) { - + symbol *sym; int i ; /* create the symbol */ sym = newSymbol (name, 0); - + /* setup return value */ sym->type = newLink (DECLARATOR); DCL_TYPE (sym->type) = FUNCTION; sym->type->next = typeFromStr(rtype); sym->etype = getSpec (sym->type); - + /* if arguments required */ if (nArgs) { value *args; args = FUNC_ARGS(sym->type) = newValue (); - + for ( i = 0 ; i < nArgs ; i++ ) { args->type = typeFromStr(atypes[i]); args->etype = getSpec (args->type); @@ -613,7 +703,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) } /* save it */ - addSymChain (sym); + addSymChain (&sym); sym->cdef = 1; allocVariables (sym); return sym; @@ -644,7 +734,7 @@ reverseParms (ast * ptree) ttree->left = ptree->left; ptree->left = ttree; } - + /* Now reverse */ ttree = ptree->left; ptree->left = ptree->right; @@ -670,7 +760,7 @@ processParms (ast *func, { RESULT_TYPE resultType; sym_link *functype; - + /* if none of them exist */ if (!defParm && !*actParm) return 0; @@ -689,7 +779,7 @@ processParms (ast *func, functype = func->ftype->next; else functype = func->ftype; - + /* if the function is being called via a pointer & */ /* it has not been defined a reentrant then we cannot */ /* have parameters */ @@ -744,7 +834,7 @@ processParms (ast *func, } /* decorate parameter */ - resultType = defParm ? getResultTypeFromType (defParm->etype) : + resultType = defParm ? getResultTypeFromType (defParm->type) : RESULT_TYPE_NONE; *actParm = decorateType (*actParm, resultType); @@ -773,7 +863,7 @@ processParms (ast *func, if (IS_INTEGRAL (ftype) && (getSize (ftype) < (unsigned) INTSIZE)) { - newType = newAst_LINK(INTTYPE); + newType = newAst_LINK(INTTYPE); } if (IS_PTR(ftype) && !IS_GENPTR(ftype)) @@ -787,14 +877,14 @@ processParms (ast *func, newType = newAst_LINK (copyLinkChain (ftype)); DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; } - + if (newType) { /* cast required; change this op to a cast. */ (*actParm)->decorated = 0; *actParm = newNode (CAST, newType, *actParm); (*actParm)->lineno = (*actParm)->right->lineno; - + decorateType (*actParm, RESULT_TYPE_NONE); } return 0; @@ -807,7 +897,7 @@ processParms (ast *func, return 0; resolveSymbols (*actParm); - + /* the parameter type must be at least castable */ if (compareType (defParm->type, (*actParm)->ftype) == 0) { @@ -823,7 +913,7 @@ processParms (ast *func, resultType = getResultTypeFromType (defParm->etype); pTree = resolveSymbols (copyAst (*actParm)); - + /* now change the current one to a cast */ (*actParm)->type = EX_OP; (*actParm)->opval.op = CAST; @@ -861,7 +951,7 @@ createIvalType (ast * sym, sym_link * type, initList * ilist) /* createIvalStruct - generates initial value for structures */ /*-----------------------------------------------------------------*/ static ast * -createIvalStruct (ast * sym, sym_link * type, initList * ilist) +createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue) { ast *rast = NULL; ast *lAst; @@ -885,12 +975,15 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) sflds->implicit = 1; lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds))); lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE); - rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_TYPE_NONE); + rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, + iloop, rast, rootValue)), + RESULT_TYPE_NONE); + } if (iloop) { werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef, - W_EXCESS_INITIALIZERS, "struct", + W_EXCESS_INITIALIZERS, "struct", sym->opval.val->sym->name); } @@ -902,7 +995,7 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) /* createIvalArray - generates code for array initialization */ /*-----------------------------------------------------------------*/ static ast * -createIvalArray (ast * sym, sym_link * type, initList * ilist) +createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue) { ast *rast = NULL; initList *iloop; @@ -915,84 +1008,83 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) if (IS_CHAR (type->next)) if ((rast = createIvalCharPtr (sym, type, - decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE)))) + decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE), + rootValue))) return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); - /* not the special case */ - if (ilist->type != INIT_DEEP) - { - werror (E_INIT_STRUCT, ""); - return NULL; - } + /* not the special case */ + if (ilist->type != INIT_DEEP) + { + werror (E_INIT_STRUCT, ""); + return NULL; + } - iloop = ilist->init.deep; - lcnt = DCL_ELEM (type); + iloop = ilist->init.deep; + lcnt = DCL_ELEM (type); - if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL)) - { - ast *aSym; + if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL)) + { + ast *aSym; - aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE); - - 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; - } - - 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; - char *filename=sym->opval.val->sym->fileDef; - - werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); - } - } - else - { - for (;;) - { - ast *aSym; - - aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); - aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE); - 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) - { - // is this a better way? at least it won't crash - char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : ""; - int lineno = iloop->lineno; - char *filename = iloop->filename; - werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); - - break; - } - } - } + aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE); + + 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; + } + + if (lcnt && size > lcnt) + { + // Array size was specified, and we have more initializers than needed. + werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef, + W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name); + } + } + else + { + for (;;) + { + ast *aSym; + + aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); + aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE); + rast = createIval (aSym, type->next, iloop, rast, rootValue); + iloop = (iloop ? iloop->next : NULL); + if (!iloop) + { + break; + } + + /* no of elements given and we */ + /* have generated for all of them */ + if (!--lcnt) + { + // is this a better way? at least it won't crash + char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : ""; + werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name); + + break; + } + } + } - /* if we have not been given a size */ - if (!DCL_ELEM (type)) + /* if we have not been given a size */ + if (!DCL_ELEM (type)) { - /* but this still updates the typedef instead of the instance ! see bug 770487 */ + /* check, if it's a flexible array */ + if (IS_STRUCT (AST_VALUE (rootValue)->type)) + AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next); + else DCL_ELEM (type) = size; } - return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); + return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); } @@ -1000,9 +1092,10 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) /* createIvalCharPtr - generates initial values for char pointers */ /*-----------------------------------------------------------------*/ static ast * -createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) +createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal) { ast *rast = NULL; + unsigned size = 0; /* if this is a pointer & right is a literal array then */ /* just assignment will do */ @@ -1020,15 +1113,19 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /* for each character generate an assignment */ /* to the array element */ char *s = SPEC_CVAL (iexpr->etype).v_char; - int i = 0; - int size = getSize (iexpr->ftype); - int symsize = getSize (type); - - if (size>symsize) + unsigned int i = 0; + unsigned int symsize = getSize (type); + + size = getSize (iexpr->ftype); + if (symsize && size>symsize) { if (size>(symsize+1)) - werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS, - "string", sym->opval.val->sym->name); + { + char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : ""; + + werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS, + "string", name); + } size = symsize; } @@ -1046,6 +1143,16 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) // now WE don't need iexpr's symbol anymore freeStringSymbol(AST_SYMBOL(iexpr)); + /* if we have not been given a size */ + if (!DCL_ELEM (type)) + { + /* check, if it's a flexible array */ + if (IS_STRUCT (AST_VALUE (rootVal)->type)) + AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next); + else + DCL_ELEM (type) = size; + } + return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); } @@ -1056,7 +1163,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /* createIvalPtr - generates initial value for pointers */ /*-----------------------------------------------------------------*/ static ast * -createIvalPtr (ast * sym, sym_link * type, initList * ilist) +createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal) { ast *rast; ast *iexpr; @@ -1069,7 +1176,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) /* if character pointer */ if (IS_CHAR (type->next)) - if ((rast = createIvalCharPtr (sym, type, iexpr))) + if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal))) return rast; return newNode ('=', sym, iexpr); @@ -1079,7 +1186,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) /* createIval - generates code for initial value */ /*-----------------------------------------------------------------*/ static ast * -createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) +createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue) { ast *rast = NULL; @@ -1088,15 +1195,15 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* if structure then */ if (IS_STRUCT (type)) - rast = createIvalStruct (sym, type, ilist); + rast = createIvalStruct (sym, type, ilist, rootValue); else /* if this is a pointer */ if (IS_PTR (type)) - rast = createIvalPtr (sym, type, ilist); + rast = createIvalPtr (sym, type, ilist, rootValue); else /* if this is an array */ if (IS_ARRAY (type)) - rast = createIvalArray (sym, type, ilist); + rast = createIvalArray (sym, type, ilist, rootValue); else /* if type is SPECIFIER */ if (IS_SPEC (type)) @@ -1112,7 +1219,8 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* initAggregates - initialises aggregate variables with initv */ /*-----------------------------------------------------------------*/ ast * initAggregates (symbol * sym, initList * ival, ast * wid) { - return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid); + ast *newAst = newAst_VALUE (symbolVal (sym)); + return createIval (newAst, sym->type, ival, wid, newAst); } /*-----------------------------------------------------------------*/ @@ -1157,7 +1265,7 @@ gatherAutoInit (symbol * autoChain) SPEC_SCLS (sym->etype) != S_CODE) { symbol *newSym; - + /* insert the symbol into the symbol table */ /* with level = 0 & name = rname */ newSym = copySymbol (sym); @@ -1169,7 +1277,7 @@ gatherAutoInit (symbol * autoChain) } else { if (getNelements(sym->type, sym->ival)>1) { werrorfl (sym->fileDef, sym->lineDef, - W_EXCESS_INITIALIZERS, "scalar", + W_EXCESS_INITIALIZERS, "scalar", sym->name); } work = newNode ('=', newAst_VALUE (symbolVal (newSym)), @@ -1191,27 +1299,27 @@ gatherAutoInit (symbol * autoChain) 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); - + lineno = sym->lineDef; + setAstLineno (ilist->init.node, sym->lineDef); + if (IS_AGGREGATE (sym->type)) { work = initAggregates (sym, sym->ival, NULL); } else { if (getNelements(sym->type, sym->ival)>1) { werrorfl (sym->fileDef, sym->lineDef, - W_EXCESS_INITIALIZERS, "scalar", + W_EXCESS_INITIALIZERS, "scalar", sym->name); } work = newNode ('=', newAst_VALUE (symbolVal (sym)), list2expr (sym->ival)); } - + // just to be sure setAstLineno (work, sym->lineDef); @@ -1239,7 +1347,7 @@ void freeStringSymbol(symbol *sym) { } } } - + /*-----------------------------------------------------------------*/ /* stringToSymbol - creates a symbol from a literal string */ /*-----------------------------------------------------------------*/ @@ -1283,7 +1391,7 @@ stringToSymbol (value * val) if (noAlloc == 0) { /* allocate it */ - addSymChain (sym); + addSymChain (&sym); allocVariables (sym); } sym->ival = NULL; @@ -1311,7 +1419,7 @@ processBlockVars (ast * tree, int *stack, int action) { *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); @@ -1338,7 +1446,7 @@ bool constExprTree (ast *cexpr) { cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE); - switch (cexpr->type) + switch (cexpr->type) { case EX_VALUE: if (IS_AST_LIT_VALUE(cexpr)) { @@ -1353,7 +1461,7 @@ bool constExprTree (ast *cexpr) { // an array's address will never change return TRUE; } - if (IS_AST_SYM_VALUE(cexpr) && + 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 @@ -1377,7 +1485,7 @@ bool constExprTree (ast *cexpr) { // cast ignored, maybe we should throw a warning here? return constExprTree(cexpr->right); } - if (cexpr->opval.op=='&') { + if (cexpr->opval.op=='&') { return TRUE; } if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) { @@ -1392,7 +1500,7 @@ bool constExprTree (ast *cexpr) { } return FALSE; } - + /*-----------------------------------------------------------------*/ /* constExprValue - returns the value of a constant expression */ /* or NULL if it is not a constant expression */ @@ -1441,14 +1549,17 @@ constExprValue (ast * cexpr, int check) } /* return the value */ - return cexpr->opval.val; - + if (IS_AST_VALUE (cexpr)) + { + return cexpr->opval.val; + } + return NULL; } /*-----------------------------------------------------------------*/ /* isLabelInAst - will return true if a given label is found */ /*-----------------------------------------------------------------*/ -bool +bool isLabelInAst (symbol * label, ast * tree) { if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree)) @@ -1468,7 +1579,7 @@ isLabelInAst (symbol * label, ast * tree) /* isLoopCountable - return true if the loop count can be determi- */ /* -ned at compile time . */ /*-----------------------------------------------------------------*/ -bool +static bool isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr, symbol ** sym, ast ** init, ast ** end) { @@ -1493,6 +1604,10 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr, else return FALSE; + /* don't reverse loop with volatile counter */ + if (IS_VOLATILE ((*sym)->type)) + return FALSE; + /* for now the symbol has to be of integral type */ if (!IS_INTEGRAL ((*sym)->type)) @@ -1533,6 +1648,8 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr, } } + else + return FALSE; /* check loop expression is of the form ++ */ if (!IS_AST_OP (loopExpr)) @@ -1579,7 +1696,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr, /*-----------------------------------------------------------------*/ /* astHasVolatile - returns true if ast contains any volatile */ /*-----------------------------------------------------------------*/ -bool +bool astHasVolatile (ast * tree) { if (!tree) @@ -1598,7 +1715,7 @@ astHasVolatile (ast * tree) /*-----------------------------------------------------------------*/ /* astHasPointer - return true if the ast contains any ptr variable */ /*-----------------------------------------------------------------*/ -bool +bool astHasPointer (ast * tree) { if (!tree) @@ -1623,7 +1740,7 @@ astHasPointer (ast * tree) /*-----------------------------------------------------------------*/ /* astHasSymbol - return true if the ast has the given symbol */ /*-----------------------------------------------------------------*/ -bool +bool astHasSymbol (ast * tree, symbol * sym) { if (!tree || IS_AST_LINK (tree)) @@ -1644,14 +1761,14 @@ astHasSymbol (ast * tree, symbol * sym) /*-----------------------------------------------------------------*/ /* astHasDeref - return true if the ast has an indirect access */ /*-----------------------------------------------------------------*/ -static bool +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); } @@ -1659,7 +1776,7 @@ astHasDeref (ast * tree) /* isConformingBody - the loop body has to conform to a set of rules */ /* for the loop to be considered reversible read on for rules */ /*-----------------------------------------------------------------*/ -bool +bool isConformingBody (ast * pbody, symbol * sym, ast * body) { @@ -1678,7 +1795,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; @@ -1754,6 +1871,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case '%': case LEFT_OP: case RIGHT_OP: + case GETABIT: + case GETBYTE: + case GETWORD: if (IS_AST_SYM_VALUE (pbody->left) && isSymbolEqual (AST_SYMBOL (pbody->left), sym)) @@ -1857,7 +1977,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /*----------------------------*/ case CALL: /* if local & not passed as paramater then ok */ - if (sym->level && !astHasSymbol(pbody->right,sym)) + if (sym->level && !astHasSymbol(pbody->right,sym)) return TRUE; return FALSE; @@ -1893,7 +2013,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 +static bool isLoopReversible (ast * loop, symbol ** loopCntrl, ast ** init, ast ** end) { @@ -1923,7 +2043,7 @@ isLoopReversible (ast * loop, symbol ** loopCntrl, /*-----------------------------------------------------------------*/ /* replLoopSym - replace the loop sym by loop sym -1 */ /*-----------------------------------------------------------------*/ -static void +static void replLoopSym (ast * body, symbol * sym) { /* reached end */ @@ -2003,7 +2123,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) /* searchLitOp - search tree (*ops only) for an ast with literal */ /*-----------------------------------------------------------------*/ static ast * -searchLitOp (ast *tree, ast **parent, const unsigned char *ops) +searchLitOp (ast *tree, ast **parent, const char *ops) { ast *ret; @@ -2013,7 +2133,7 @@ searchLitOp (ast *tree, ast **parent, const unsigned char *ops) if (tree->right && IS_AST_OP(tree->right) && tree->right->right && - (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1])) + (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1])) { if (IS_LITERAL (RTYPE (tree->right)) != IS_LITERAL (LTYPE (tree->right))) @@ -2030,7 +2150,7 @@ searchLitOp (ast *tree, ast **parent, const unsigned char *ops) if (tree->left && IS_AST_OP(tree->left) && tree->left->right && - (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1])) + (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1])) { if (IS_LITERAL (RTYPE (tree->left)) != IS_LITERAL (LTYPE (tree->left))) @@ -2060,7 +2180,7 @@ getResultTypeFromType (sym_link *type) if (IS_BITFIELD (type)) { int blen = SPEC_BLEN (type); - + if (blen <= 1) return RESULT_TYPE_BIT; if (blen <= 8) @@ -2069,8 +2189,7 @@ getResultTypeFromType (sym_link *type) } if (IS_CHAR (type)) return RESULT_TYPE_CHAR; - if ( IS_INT (type) - && !IS_LONG (type)) + if (IS_INT (type) && !IS_LONG (type)) return RESULT_TYPE_INT; return RESULT_TYPE_OTHER; } @@ -2079,24 +2198,38 @@ getResultTypeFromType (sym_link *type) /* addCast - adds casts to a type specified by RESULT_TYPE */ /*-----------------------------------------------------------------*/ static ast * -addCast (ast *tree, RESULT_TYPE resultType, bool upcast) +addCast (ast *tree, RESULT_TYPE resultType, bool promote) { sym_link *newLink; bool upCasted = FALSE; - + switch (resultType) { case RESULT_TYPE_NONE: - /* char: promote to int */ - if (!upcast || + /* if thing smaller than int must be promoted to int */ + if (!promote || getSize (tree->etype) >= INTSIZE) + /* promotion not necessary or already an int */ + return tree; + /* char and bits: promote to int */ + newLink = newIntLink(); + upCasted = TRUE; + break; + case RESULT_TYPE_BIT: + if (!promote || + /* already an int */ + bitsForType (tree->etype) >= 16 || + /* bit to bit operation: don't promote, the code generators + hopefully know everything about promotion rules */ + bitsForType (tree->etype) == 1) return tree; newLink = newIntLink(); upCasted = TRUE; break; case RESULT_TYPE_CHAR: if (IS_CHAR (tree->etype) || - IS_FLOAT(tree->etype)) + IS_FLOAT(tree->etype) || + IS_FIXED(tree->etype)) return tree; newLink = newCharLink(); break; @@ -2109,17 +2242,17 @@ addCast (ast *tree, RESULT_TYPE resultType, bool upcast) } #endif /* char: promote to int */ - if (!upcast || + if (!promote || getSize (tree->etype) >= INTSIZE) return tree; newLink = newIntLink(); upCasted = TRUE; break; + case RESULT_TYPE_IFX: case RESULT_TYPE_OTHER: - if (!upcast) - return tree; - /* return type is long, float: promote char to int */ - if (getSize (tree->etype) >= INTSIZE) + if (!promote || + /* return type is ifx, long, float: promote char to int */ + getSize (tree->etype) >= INTSIZE) return tree; newLink = newIntLink(); upCasted = TRUE; @@ -2145,6 +2278,9 @@ resultTypePropagate (ast *tree, RESULT_TYPE resultType) { switch (tree->opval.op) { + case AND_OP: + case OR_OP: + return resultType; case '=': case '?': case ':': @@ -2191,7 +2327,7 @@ getLeftResultType (ast *tree, RESULT_TYPE resultType) case '[': if (!IS_ARRAY (LTYPE (tree))) return resultType; - if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256) + if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255) return RESULT_TYPE_CHAR; return resultType; default: @@ -2199,10 +2335,77 @@ getLeftResultType (ast *tree, RESULT_TYPE resultType) } } +/*------------------------------------------------------------------*/ +/* gatherImplicitVariables: assigns correct type information to */ +/* symbols and values created by replaceAstWithTemporary */ +/* and adds the symbols to the declarations list of the */ +/* innermost block that contains them */ +/*------------------------------------------------------------------*/ +void +gatherImplicitVariables (ast * tree, ast * block) +{ + if (!tree) + return; + + if (tree->type == EX_OP && tree->opval.op == BLOCK) + { + /* keep track of containing scope */ + block = tree; + } + if (tree->type == EX_OP && tree->opval.op == '=' && + tree->left->type == EX_VALUE && tree->left->opval.val->sym) + { + symbol *assignee = tree->left->opval.val->sym; + + /* special case for assignment to compiler-generated temporary variable: + compute type of RHS, and set the symbol's type to match */ + if (assignee->type == NULL && assignee->infertype) { + ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE); + + if (dtr != tree->right) + tree->right = dtr; + + assignee->type = copyLinkChain(TTYPE(dtr)); + assignee->etype = getSpec(assignee->type); + SPEC_SCLS (assignee->etype) = S_AUTO; + SPEC_OCLS (assignee->etype) = NULL; + SPEC_EXTR (assignee->etype) = 0; + SPEC_STAT (assignee->etype) = 0; + SPEC_VOLATILE (assignee->etype) = 0; + SPEC_ABSA (assignee->etype) = 0; + + wassertl(block != NULL, "implicit variable not contained in block"); + wassert(assignee->next == NULL); + if (block != NULL) { + symbol **decl = &(block->values.sym); + + while (*decl) { + wassert(*decl != assignee); /* should not already be in list */ + decl = &( (*decl)->next ); + } + + *decl = assignee; + } + } + } + if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) && + tree->opval.val->type == NULL && + tree->opval.val->sym && + tree->opval.val->sym->infertype) + { + /* fixup type of value for compiler-inferred temporary var */ + tree->opval.val->type = tree->opval.val->sym->type; + tree->opval.val->etype = tree->opval.val->sym->etype; + } + + gatherImplicitVariables(tree->left, block); + gatherImplicitVariables(tree->right, block); +} + /*--------------------------------------------------------------------*/ /* decorateType - compute type for this tree, also does type checking.*/ /* This is done bottom up, since type has to flow upwards. */ -/* resultType flows top-down and forces e.g. char-arithmetik, if the */ +/* resultType flows top-down and forces e.g. char-arithmetic, if the */ /* result is a char and the operand(s) are int's. */ /* It also does constant folding, and parameter checking. */ /*--------------------------------------------------------------------*/ @@ -2245,7 +2448,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /*----------------------------*/ /* leaf has been reached */ /*----------------------------*/ - lineno=tree->lineno; + lineno = tree->lineno; /* if this is of type value */ /* just get the type */ if (tree->type == EX_VALUE) @@ -2268,31 +2471,29 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* 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); + werrorfl (tree->filename, tree->lineno, 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 (tree->opval.val->sym->implicit) + { + /* if implicit i.e. struct/union member then no type */ + TTYPE (tree) = TETYPE (tree) = NULL; + } else { + /* copy the type from the value into the ast */ + COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type); - /* 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; - } + /* and mark the symbol as referenced */ + tree->opval.val->sym->isref = 1; } } + else + wassert(0); /* unreached: all values are literals or symbols */ return tree; } @@ -2355,7 +2556,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) in tree->left->?type. If the op is e.g. '=' we extract the type information from there and propagate it to the right branch. */ resultTypeProp = getLeftResultType (tree, resultTypeProp); - + switch (tree->opval.op) { case '?': @@ -2363,12 +2564,18 @@ decorateType (ast * tree, RESULT_TYPE resultType) expansions might rely on this */ dtr = tree->right; break; - case CALL: + case CALL: /* decorate right side for CALL (parameter list) in processParms(); there is resultType available */ dtr = tree->right; break; - default: + case SIZEOF: + /* don't allocate string if it is a sizeof argument */ + ++noAlloc; + dtr = decorateType (tree->right, resultTypeProp); + --noAlloc; + break; + default: dtr = decorateType (tree->right, resultTypeProp); break; } @@ -2396,21 +2603,21 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* first check if this is a array or a pointer */ if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree)))) { - werror (E_NEED_ARRAY_PTR, "[]"); + werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]"); goto errorTreeReturn; } /* check if the type of the idx */ if (!IS_INTEGRAL (RTYPE (tree))) { - werror (E_IDX_NOT_INT); + werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT); goto errorTreeReturn; } /* if the left is an rvalue then error */ if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "array access"); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access"); goto errorTreeReturn; } @@ -2420,12 +2627,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) int arraySize = DCL_ELEM (LTYPE (tree)); if (arraySize && arrayIndex >= arraySize) { - werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize); + werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize); } } RRVAL (tree) = 1; COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next); + SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree)); return tree; /*------------------------------------------------------------------*/ @@ -2436,7 +2644,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* if this is not a structure */ if (!IS_STRUCT (LTYPE (tree))) { - werror (E_STRUCT_UNION, "."); + werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "."); goto errorTreeReturn; } TTYPE (tree) = structElemType (LTYPE (tree), @@ -2453,13 +2661,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* if not pointer to a structure */ if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree))) { - werror (E_PTR_REQD); + werrorfl (tree->filename, tree->lineno, E_PTR_REQD); goto errorTreeReturn; } if (!IS_STRUCT (LTYPE (tree)->next)) { - werror (E_STRUCT_UNION, "->"); + werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->"); goto errorTreeReturn; } @@ -2471,19 +2679,19 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* adjust the storage class */ switch (DCL_TYPE(tree->left->ftype)) { case POINTER: - SPEC_SCLS(TETYPE(tree)) = S_DATA; + SPEC_SCLS(TETYPE(tree)) = S_DATA; break; case FPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_XDATA; + SPEC_SCLS(TETYPE(tree)) = S_XDATA; break; case CPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_CODE; + SPEC_SCLS(TETYPE(tree)) = S_CODE; break; case GPOINTER: SPEC_SCLS (TETYPE (tree)) = 0; break; case PPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; break; case IPOINTER: SPEC_SCLS(TETYPE(tree)) = S_IDATA; @@ -2498,7 +2706,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) case FUNCTION: break; } - + /* This breaks with extern declarations, bitfields, and perhaps other */ /* cases (gcse). Let's leave this optimization disabled for now and */ /* ponder if there's a safe way to do this. -- EEP */ @@ -2527,7 +2735,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) 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; @@ -2536,7 +2744,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->right = NULL; } #endif - + return tree; /*------------------------------------------------------------------*/ @@ -2549,7 +2757,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree)); COPYTYPE (TTYPE (tree), TETYPE (tree), ltc); if (!tree->initMode && IS_CONSTANT(TTYPE(tree))) - werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--"); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--"); if (tree->right) RLVAL (tree) = 1; @@ -2569,8 +2777,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { - werror (E_BITWISE_OP); - werror (W_CONTINUE, "left & right types are "); + werrorfl (tree->filename, tree->lineno, E_BITWISE_OP); + werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, ","); printTypeChain (RTYPE (tree), stderr); @@ -2594,7 +2802,34 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* see if this is a GETHBIT operation if yes then return that */ { - ast *otree = optimizeGetHbit (tree); + ast *otree = optimizeGetHbit (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETABIT operation if yes + then return that */ + { + ast *otree = optimizeGetAbit (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETBYTE operation if yes + then return that */ + { + ast *otree = optimizeGetByte (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETWORD operation if yes + then return that */ + { + ast *otree = optimizeGetWord (tree, resultType); if (otree != tree) return decorateType (otree, RESULT_TYPE_NONE); @@ -2627,7 +2862,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) } LRVAL (tree) = RRVAL (tree) = 1; - + TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), resultType, @@ -2645,13 +2880,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* if bit field then error */ if (IS_BITVAR (tree->left->etype)) { - werror (E_ILLEGAL_ADDR, "address of bit variable"); + werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable"); goto errorTreeReturn; } if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER) { - werror (E_ILLEGAL_ADDR, "address of register variable"); + werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable"); goto errorTreeReturn; } @@ -2663,13 +2898,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (IS_LITERAL(LTYPE(tree))) { - werror (E_ILLEGAL_ADDR, "address of literal"); + werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal"); goto errorTreeReturn; } if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "address of"); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of"); goto errorTreeReturn; } if (!LETYPE (tree)) @@ -2723,12 +2958,12 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* bitwise or */ /*----------------------------*/ case '|': - /* if the rewrite succeeds then don't go any furthur */ + /* if the rewrite succeeds then don't go any further */ { ast *wtree = optimizeRRCRLC (tree); if (wtree != tree) return decorateType (wtree, RESULT_TYPE_NONE); - + wtree = optimizeSWAP (tree); if (wtree != tree) return decorateType (wtree, RESULT_TYPE_NONE); @@ -2768,8 +3003,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) case '^': if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { - werror (E_BITWISE_OP); - werror (W_CONTINUE, "left & right types are "); + werrorfl (tree->filename, tree->lineno, E_BITWISE_OP); + werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, ","); printTypeChain (RTYPE (tree), stderr); @@ -2834,7 +3069,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) case '/': if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) { - werror (E_INVALID_OP, "divide"); + werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide"); goto errorTreeReturn; } /* if they are both literal then */ @@ -2863,7 +3098,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* rearrange the tree */ if (IS_LITERAL (RTYPE (tree)) /* avoid infinite loop */ - && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1) + && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 1) { ast *parent; ast *litTree = searchLitOp (tree, &parent, "/"); @@ -2901,8 +3136,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) case '%': if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { - werror (E_BITWISE_OP); - werror (W_CONTINUE, "left & right types are "); + werrorfl (tree->filename, tree->lineno, E_BITWISE_OP); + werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, ","); printTypeChain (RTYPE (tree), stderr); @@ -2938,13 +3173,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) { if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree))) { - werror (E_PTR_REQD); + werrorfl (tree->filename, tree->lineno, E_PTR_REQD); goto errorTreeReturn; } if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "pointer deref"); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref"); goto errorTreeReturn; } if (IS_ADDRESS_OF_OP(tree->left)) @@ -2960,16 +3195,16 @@ decorateType (ast * tree, RESULT_TYPE resultType) SPEC_SCLS(TETYPE(tree)) = S_DATA; break; case FPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_XDATA; + SPEC_SCLS(TETYPE(tree)) = S_XDATA; break; case CPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_CODE; + SPEC_SCLS(TETYPE(tree)) = S_CODE; break; case GPOINTER: SPEC_SCLS (TETYPE (tree)) = 0; break; case PPOINTER: - SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; break; case IPOINTER: SPEC_SCLS(TETYPE(tree)) = S_IDATA; @@ -2993,7 +3228,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /*----------------------------*/ if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) { - werror (E_INVALID_OP, "multiplication"); + werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication"); goto errorTreeReturn; } @@ -3057,7 +3292,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) { if (!IS_ARITHMETIC (LTYPE (tree))) { - werror (E_UNARY_OP, '+'); + werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+'); goto errorTreeReturn; } @@ -3085,21 +3320,21 @@ decorateType (ast * tree, RESULT_TYPE resultType) if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) && (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)))) { - werror (E_PTR_PLUS_PTR); + werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR); goto errorTreeReturn; } if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree))) { - werror (E_PLUS_INVALID, "+"); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+"); goto errorTreeReturn; } if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree))) { - werror (E_PLUS_INVALID, "+"); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+"); goto errorTreeReturn; } /* if they are both literal then */ @@ -3186,7 +3421,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) resultType, tree->opval.op)); } - + return tree; /*------------------------------------------------------------------*/ @@ -3200,7 +3435,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!IS_ARITHMETIC (LTYPE (tree))) { - werror (E_UNARY_OP, tree->opval.op); + werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op); goto errorTreeReturn; } @@ -3211,11 +3446,15 @@ decorateType (ast * tree, RESULT_TYPE resultType) 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; } + tree->left = addCast (tree->left, resultType, TRUE); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + NULL, + resultType, + tree->opval.op)); LRVAL (tree) = 1; - TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree)); return tree; } @@ -3228,7 +3467,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) IS_ARRAY (LTYPE (tree)) || IS_ARITHMETIC (LTYPE (tree)))) { - werror (E_PLUS_INVALID, "-"); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-"); goto errorTreeReturn; } @@ -3236,7 +3475,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) IS_ARRAY (RTYPE (tree)) || IS_ARITHMETIC (RTYPE (tree)))) { - werror (E_PLUS_INVALID, "-"); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-"); goto errorTreeReturn; } @@ -3244,7 +3483,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) || IS_INTEGRAL (RTYPE (tree)))) { - werror (E_PLUS_INVALID, "-"); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-"); goto errorTreeReturn; } @@ -3303,7 +3542,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* rearrange the tree */ if (IS_LITERAL (RTYPE (tree)) /* avoid infinite loop */ - && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0) + && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 0) { ast *litTree, *litParent; litTree = searchLitOp (tree, &litParent, "+-"); @@ -3331,7 +3570,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->right = litParent->left; litParent->left = tTree; litTree->opval.op = '+'; - + tree->decorated = 0; decorateType (tree, resultType); } @@ -3357,7 +3596,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* can be only integral type */ if (!IS_INTEGRAL (LTYPE (tree))) { - werror (E_UNARY_OP, tree->opval.op); + werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op); goto errorTreeReturn; } @@ -3370,7 +3609,23 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = TTYPE (tree) = tree->opval.val->type; return addCast (tree, resultType, TRUE); } - tree->left = addCast (tree->left, resultType, TRUE); + + if (resultType == RESULT_TYPE_BIT && + IS_UNSIGNED (tree->left->etype) && + getSize (tree->left->etype) < INTSIZE) + { + /* promotion rules are responsible for this strange result: + bit -> int -> ~int -> bit + uchar -> int -> ~int -> bit + */ + werrorfl (tree->filename, tree->lineno, W_COMPLEMENT); + + /* optimize bit-result, even if we optimize a buggy source */ + tree->type = EX_VALUE; + tree->opval.val = constVal ("1"); + } + else + tree->left = addCast (tree->left, resultType, TRUE); LRVAL (tree) = 1; COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); return tree; @@ -3385,10 +3640,24 @@ decorateType (ast * tree, RESULT_TYPE resultType) !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree))) { - werror (E_UNARY_OP, tree->opval.op); + werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op); goto errorTreeReturn; } + /* if left is another '!' */ + if (tree->left->opval.op == '!') + { + /* remove double '!!X' by 'X ? 1 : 0' */ + tree->opval.op = '?'; + tree->left = tree->left->left; + tree->right = newNode (':', + newAst_VALUE (constVal ("1")), + newAst_VALUE (constVal ("0"))); + tree->right->lineno = tree->lineno; + tree->decorated = 0; + return decorateType (tree, resultType); + } + /* if left is a literal then do it */ if (IS_LITERAL (LTYPE (tree))) { @@ -3399,7 +3668,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; } LRVAL (tree) = 1; - TTYPE (tree) = TETYPE (tree) = newCharLink (); + TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink(); return tree; /*------------------------------------------------------------------*/ @@ -3414,15 +3683,24 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; case GETHBIT: - TTYPE (tree) = TETYPE (tree) = newCharLink (); + case GETABIT: + TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink(); + return tree; + + case GETBYTE: + TTYPE (tree) = TETYPE (tree) = newCharLink(); + return tree; + + case GETWORD: + TTYPE (tree) = TETYPE (tree) = newIntLink(); return tree; case LEFT_OP: case RIGHT_OP: if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype)) { - werror (E_SHIFT_OP_INVALID); - werror (W_CONTINUE, "left & right types are "); + werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID); + werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, ","); printTypeChain (RTYPE (tree), stderr); @@ -3433,7 +3711,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* make smaller type only if it's a LEFT_OP */ if (tree->opval.op == LEFT_OP) tree->left = addCast (tree->left, resultType, TRUE); - + /* if they are both literal then */ /* rewrite the tree */ if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree))) @@ -3448,6 +3726,24 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; } + /* see if this is a GETBYTE operation if yes + then return that */ + { + ast *otree = optimizeGetByte (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETWORD operation if yes + then return that */ + { + ast *otree = optimizeGetWord (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + LRVAL (tree) = RRVAL (tree) = 1; if (tree->opval.op == LEFT_OP) { @@ -3468,14 +3764,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* if only the right side is a literal & we are shifting more than size of the left operand then zero */ if (IS_LITERAL (RTYPE (tree)) && - ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >= + ((TYPE_TARGET_ULONG) floatFromVal (valFromType (RETYPE (tree)))) >= (getSize (TETYPE (tree)) * 8)) { if (tree->opval.op==LEFT_OP || (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) { - lineno=tree->lineno; - werror (W_SHIFT_CHANGED, + werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED, (tree->opval.op == LEFT_OP ? "left" : "right")); tree->type = EX_VALUE; tree->left = tree->right = NULL; @@ -3495,7 +3790,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* cannot cast to an aggregate type */ if (IS_AGGREGATE (LTYPE (tree))) { - werror (E_CAST_ILLEGAL); + werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL); goto errorTreeReturn; } @@ -3503,6 +3798,13 @@ decorateType (ast * tree, RESULT_TYPE resultType) changePointer(LTYPE(tree)); checkTypeSanity(LETYPE(tree), "(cast)"); + /* if 'from' and 'to' are the same remove the superfluous cast, */ + /* this helps other optimizations */ + if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1) + { + return tree->right; + } + /* If code memory is read only, then pointers to code memory */ /* implicitly point to constants -- make this explicit */ { @@ -3535,7 +3837,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) } 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); + werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC); TTYPE(tree) = newLink(DECLARATOR); DCL_TYPE(TTYPE(tree)) = FPOINTER; TTYPE(tree)->next = rest; @@ -3556,7 +3858,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) 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, + werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag, SPEC_STRUCT(LETYPE(tree))->tag); } #endif @@ -3564,10 +3866,40 @@ decorateType (ast * tree, RESULT_TYPE resultType) && IS_AST_SYM_VALUE (tree->right->left) && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) { + symbol * sym = AST_SYMBOL (tree->right->left); + unsigned int gptype = 0; + unsigned int addr = SPEC_ADDR (sym->etype); + + if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) + || TARGET_IS_PIC16) ) + { + switch (SPEC_SCLS (sym->etype)) + { + case S_CODE: + gptype = GPTYPE_CODE; + break; + case S_XDATA: + gptype = GPTYPE_FAR; + break; + case S_DATA: + case S_IDATA: + gptype = GPTYPE_NEAR; + break; + case S_PDATA: + gptype = GPTYPE_XSTACK; + break; + default: + gptype = 0; + + if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED)) + gptype = GPTYPE_NEAR; + } + addr |= gptype << (8*(GPTRSIZE - 1)); + } + tree->type = EX_VALUE; tree->opval.val = - valCastLiteral (LTYPE (tree), - SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype)); + valCastLiteral (LTYPE (tree), addr); TTYPE (tree) = tree->opval.val->type; TETYPE (tree) = getSpec (TTYPE (tree)); tree->left = NULL; @@ -3680,7 +4012,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) !IS_ARRAY (LTYPE (tree)) && !IS_INTEGRAL (LTYPE (tree))) { - werror (E_COMPARE_OP); + werrorfl (tree->filename, tree->lineno, E_COMPARE_OP); goto errorTreeReturn; } @@ -3688,7 +4020,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) !IS_ARRAY (RTYPE (tree)) && !IS_INTEGRAL (RTYPE (tree))) { - werror (E_COMPARE_OP); + werrorfl (tree->filename, tree->lineno, E_COMPARE_OP); goto errorTreeReturn; } /* if they are both literal then */ @@ -3706,7 +4038,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; } LRVAL (tree) = RRVAL (tree) = 1; - TTYPE (tree) = TETYPE (tree) = newCharLink (); + TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink(); return tree; /*------------------------------------------------------------------*/ @@ -3738,7 +4070,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) } if (compareType (LTYPE (tree), RTYPE (tree)) == 0) { - werror (E_COMPARE_OP); + werrorfl (tree->filename, tree->lineno, E_COMPARE_OP); fprintf (stderr, "comparing type "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, "to type "); @@ -3755,7 +4087,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (compareType (LTYPE (tree), RTYPE (tree)) == 0) { - werror (E_COMPARE_OP); + werrorfl (tree->filename, tree->lineno, E_COMPARE_OP); fprintf (stderr, "comparing type "); printTypeChain (LTYPE (tree), stderr); fprintf (stderr, "to type "); @@ -3764,36 +4096,71 @@ decorateType (ast * tree, RESULT_TYPE resultType) goto errorTreeReturn; } } - /* if unsigned value < 0 then always false */ + + { + CCR_RESULT ccr_result = CCR_OK; + + /* if left is integral and right is literal + then check constant range */ + if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree))) + ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree), + tree->opval.op, FALSE); + if (ccr_result == CCR_OK && + IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) + ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree), + tree->opval.op, TRUE); + switch (ccr_result) + { + case CCR_ALWAYS_TRUE: + case CCR_ALWAYS_FALSE: + if (!options.lessPedantic) + werrorfl (tree->filename, tree->lineno, W_COMP_RANGE, + ccr_result == CCR_ALWAYS_TRUE ? "true" : "false"); + return decorateType (newAst_VALUE (constVal ( + ccr_result == CCR_ALWAYS_TRUE ? "1" : "0")), + resultType); + case CCR_OK: + default: + break; + } + } + /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */ - if (SPEC_USIGN(LETYPE(tree)) && - !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */ + if (tree->opval.op == '>' && + 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 == '>') + if (resultType == RESULT_TYPE_IFX) { - if (resultType == RESULT_TYPE_IFX) - { - /* the parent is an ifx: */ - /* if (unsigned value) */ - return tree->left; - } - - /* (unsigned value) ? 1 : 0 */ - tree->opval.op = '?'; - tree->right = newNode (':', - newAst_VALUE (constVal ("1")), - tree->right); /* val 0 */ - tree->right->lineno = tree->lineno; - tree->right->left->lineno = tree->lineno; - decorateType (tree->right, RESULT_TYPE_NONE); + /* the parent is an ifx: */ + /* if (unsigned value) */ + return tree->left; } + + /* (unsigned value) ? 1 : 0 */ + tree->opval.op = '?'; + tree->right = newNode (':', + newAst_VALUE (constVal ("1")), + tree->right); /* val 0 */ + tree->right->lineno = tree->lineno; + tree->right->left->lineno = tree->lineno; + tree->decorated = 0; + return decorateType (tree, resultType); } + + /* 'ifx (op == 0)' -> 'ifx (!(op))' */ + if (IS_LITERAL(RTYPE(tree)) && + floatFromVal (valFromType (RETYPE (tree))) == 0 && + tree->opval.op == EQ_OP && + resultType == RESULT_TYPE_IFX) + { + tree->opval.op = '!'; + tree->right = NULL; + tree->decorated = 0; + return decorateType (tree, resultType); + } + /* if they are both literal then */ /* rewrite the tree */ if (IS_LITERAL (RTYPE (tree)) && @@ -3808,8 +4175,84 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->opval.val->type); return tree; } + + /* if one is 'signed char ' and the other one is 'unsigned char' */ + /* it's necessary to promote to int */ + if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) && + (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree)))) + { + /* Literals are 'optimized' to 'unsigned char'. Try to figure out, + if it's possible to use a 'signed char' */ + + /* is left a 'unsigned char'? */ + if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) && + /* the value range of a 'unsigned char' is 0...255; + if the actual value is < 128 it can be changed to signed */ + (int) floatFromVal (valFromType (RETYPE (tree))) < 128) + { + /* now we've got 2 'signed char'! */ + SPEC_USIGN (RETYPE (tree)) = 0; + } + /* same test for the left operand: */ + else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) && + (int) floatFromVal (valFromType (LETYPE (tree))) < 128) + { + SPEC_USIGN (LETYPE (tree)) = 0; + } + else + { + werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR); + tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE); + tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE); + } + } + LRVAL (tree) = RRVAL (tree) = 1; - TTYPE (tree) = TETYPE (tree) = newCharLink (); + TTYPE (tree) = TETYPE (tree) = newBoolLink (); + + /* condition transformations */ + { + unsigned transformedOp = 0; + + switch (tree->opval.op) + { + case '<': /* transform (a < b) to !(a >= b) */ + if (port->lt_nge) + transformedOp = GE_OP; + break; + case '>': /* transform (a > b) to !(a <= b) */ + if (port->gt_nle) + transformedOp = LE_OP; + break; + case LE_OP: /* transform (a <= b) to !(a > b) */ + if (port->le_ngt) + transformedOp = '>'; + break; + case GE_OP: /* transform (a >= b) to !(a < b) */ + if (port->ge_nlt) + transformedOp = '<'; + break; + case NE_OP: /* transform (a != b) to !(a == b) */ + if (port->ne_neq) + transformedOp = EQ_OP; + break; + case EQ_OP: /* transform (a == b) to !(a != b) */ + if (port->eq_nne) + transformedOp = NE_OP; + break; + default: + break; + } + if (transformedOp) + { + tree->opval.op = transformedOp; + tree->decorated = 0; + tree = newNode ('!', tree, NULL); + tree->lineno = tree->left->lineno; + return decorateType (tree, resultType); + } + } + return tree; /*------------------------------------------------------------------*/ @@ -3820,6 +4263,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* change the type to a integer */ { int size = getSize (tree->right->ftype); + SNPRINTF(buffer, sizeof(buffer), "%d", size); if (!size && !IS_VOID(tree->right->ftype)) werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE); @@ -3829,6 +4273,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->right = tree->left = NULL; TETYPE (tree) = getSpec (TTYPE (tree) = tree->opval.val->type); + return tree; /*------------------------------------------------------------------*/ @@ -3849,6 +4294,9 @@ decorateType (ast * tree, RESULT_TYPE resultType) case V_FLOAT: typeofv = TYPEOF_FLOAT; break; + case V_FIXED16X16: + typeofv = TYPEOF_FIXED16X16; + break; case V_CHAR: typeofv = TYPEOF_CHAR; break; @@ -3936,7 +4384,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) && (compareType (RTYPE (tree), LTYPE (tree)) == 0)) { - werror (E_TYPE_MISMATCH, "conditional operator", " "); + werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " "); goto errorTreeReturn; } @@ -3957,18 +4405,18 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree))) { - werror (E_OPS_INTEGRAL); + werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL); goto errorTreeReturn; } RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); if (!tree->initMode && IS_CONSTANT (LTYPE (tree))) - werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/="); goto errorTreeReturn; } LLVAL (tree) = 1; @@ -3984,18 +4432,18 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree))) { - werror (E_OPS_INTEGRAL); + werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL); goto errorTreeReturn; } RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<="); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<="); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<="); goto errorTreeReturn; } LLVAL (tree) = 1; @@ -4010,14 +4458,14 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!(IS_PTR (LTYPE (tree)) || IS_ARITHMETIC (LTYPE (tree)))) { - werror (E_PLUS_INVALID, "-="); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-="); goto errorTreeReturn; } if (!(IS_PTR (RTYPE (tree)) || IS_ARITHMETIC (RTYPE (tree)))) { - werror (E_PLUS_INVALID, "-="); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-="); goto errorTreeReturn; } RRVAL (tree) = 1; @@ -4028,11 +4476,11 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, "-="); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "-="); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-="); goto errorTreeReturn; } LLVAL (tree) = 1; @@ -4048,19 +4496,19 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* if both pointers then problem */ if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) { - werror (E_PTR_PLUS_PTR); + werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR); goto errorTreeReturn; } if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree))) { - werror (E_PLUS_INVALID, "+="); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+="); goto errorTreeReturn; } if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree))) { - werror (E_PLUS_INVALID, "+="); + werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+="); goto errorTreeReturn; } RRVAL (tree) = 1; @@ -4071,11 +4519,11 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) - werror (E_CODE_WRITE, "+="); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+="); if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "+="); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+="); goto errorTreeReturn; } @@ -4093,14 +4541,14 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* cannot be an aggregate */ if (IS_AGGREGATE (LTYPE (tree))) { - werror (E_AGGR_ASSIGN); + werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN); goto errorTreeReturn; } /* they should either match or be castable */ if (compareType (LTYPE (tree), RTYPE (tree)) == 0) { - werror (E_TYPE_MISMATCH, "assignment", " "); + werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " "); printFromToType(RTYPE(tree),LTYPE(tree)); } @@ -4108,7 +4556,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) then report error */ if (IS_VOID (LTYPE (tree))) { - werror (E_CAST_ZERO); + werrorfl (tree->filename, tree->lineno, E_CAST_ZERO); printFromToType(RTYPE(tree), LTYPE(tree)); } @@ -4118,11 +4566,11 @@ decorateType (ast * tree, RESULT_TYPE resultType) LLVAL (tree) = 1; if (!tree->initMode ) { if (IS_CONSTANT(LTYPE(tree))) - werror (E_CODE_WRITE, "="); + werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "="); } if (LRVAL (tree)) { - werror (E_LVALUE_REQUIRED, "="); + werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "="); goto errorTreeReturn; } @@ -4141,7 +4589,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* function call */ /*----------------------------*/ case CALL: - + /* undo any explicit pointer derefernce; PCALL will handle it instead */ if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP) { @@ -4150,8 +4598,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) } /* require a function or pointer to function */ - if (!IS_FUNC (LTYPE (tree)) - && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next))) + if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree))) { werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED); goto errorTreeReturn; @@ -4162,11 +4609,14 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!tree->right || !tree->right->decorated) { - sym_link *functype; + sym_link *functype; parmNumber = 1; - if (IS_CODEPTR(LTYPE(tree))) - functype = LTYPE (tree)->next; + if (IS_FUNCPTR (LTYPE (tree))) + { + functype = LTYPE (tree)->next; + processFuncPtrArgs (functype); + } else functype = LTYPE (tree); @@ -4175,8 +4625,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) { goto errorTreeReturn; } - - if ((options.stackAuto || IFFUNC_ISREENT (functype)) && + + if ((options.stackAuto || IFFUNC_ISREENT (functype)) && !IFFUNC_ISBUILTIN(functype)) { reverseParms (tree->right); @@ -4227,7 +4677,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) if (!IS_VOID (currFunc->type->next) && tree->right == NULL) { - werror (W_VOID_FUNC, currFunc->name); + werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name); goto errorTreeReturn; } @@ -4266,9 +4716,12 @@ decorateType (ast * tree, RESULT_TYPE resultType) /*----------------------------*/ case FOR: - decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE); - decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE); - decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE); + AST_FOR (tree, initExpr) = decorateType ( + resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE); + AST_FOR (tree, condExpr) = decorateType ( + resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE); + AST_FOR (tree, loopExpr) = decorateType ( + resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE); /* if the for loop is reversible then reverse it otherwise do what we normally @@ -4290,7 +4743,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->left), RESULT_TYPE_NONE); } case PARAM: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__, "node PARAM shouldn't be processed here"); /* but in processParams() */ return tree; @@ -4341,13 +4794,23 @@ sizeofOp (sym_link * type) /*-----------------------------------------------------------------*/ /* backPatchLabels - change and or not operators to flow control */ /*-----------------------------------------------------------------*/ -ast * +static ast * backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel) { if (!tree) return NULL; + /* while-loops insert a label between the IFX and the condition, + therefore look behind the label too */ + if (tree->opval.op == LABEL && + tree->right && + IS_ANDORNOT (tree->right)) + { + tree->right = backPatchLabels (tree->right, trueLabel, falseLabel); + return tree; + } + if (!(IS_ANDORNOT (tree))) return tree; @@ -4406,25 +4869,18 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel) /* change not */ if (IS_NOT (tree)) { - int wasnot = IS_NOT (tree->left); + /* call with exchanged labels */ tree->left = backPatchLabels (tree->left, falseLabel, trueLabel); - /* if the left is already a IFX */ + /* if left isn't 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 = newNode (IFX, tree->left, NULL); tree->left->trueLabel = falseLabel; tree->left->falseLabel = trueLabel; } return tree->left; - } + } if (IS_IFX (tree)) { @@ -4450,7 +4906,7 @@ createBlock (symbol * decl, ast * body) ex = newNode (BLOCK, NULL, body); ex->values.sym = decl; - + ex->level++; ex->lineno = 0; return ex; @@ -4569,7 +5025,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) } /* create the case label */ - SNPRINTF(caseLbl, sizeof(caseLbl), + SNPRINTF(caseLbl, sizeof(caseLbl), "_case_%d_%d", swStat->values.switchVals.swNum, (int) floatFromVal (caseVal->opval.val)); @@ -4698,11 +5154,13 @@ createDo (symbol * trueLabel, symbol * continueLabel, /* if the body does not exist then it is simple */ if (!doBody) { - condAst = backPatchLabels (condAst, continueLabel, NULL); + condAst = backPatchLabels (condAst, continueLabel, falseLabel); doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst) : newNode (IFX, createLabel (continueLabel, condAst), NULL)); doTree->trueLabel = continueLabel; doTree->falseLabel = NULL; + + doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL)); return doTree; } @@ -4836,41 +5294,194 @@ createWhile (symbol * trueLabel, symbol * continueLabel, } /*-----------------------------------------------------------------*/ -/* optimizeGetHbit - get highest order bit of the expression */ +/* isShiftRightLitVal _BitAndLitVal - helper function */ /*-----------------------------------------------------------------*/ -ast * -optimizeGetHbit (ast * tree) +static ast * +isShiftRightLitVal_BitAndLitVal (ast * tree) { - int i, j; /* if this is not a bit and */ if (!IS_BITAND (tree)) - return tree; + return NULL; + + /* will look for tree of the form + ( expr >> litval2) & litval1 */ + if (!IS_AST_LIT_VALUE (tree->right)) + return NULL; + + if (!IS_RIGHT_OP (tree->left)) + return NULL; + + if (!IS_AST_LIT_VALUE (tree->left->right)) + return NULL; + + return tree->left->left; +} + +/*-----------------------------------------------------------------*/ +/* isBitAndPowOf2 - helper function */ +/*-----------------------------------------------------------------*/ +static int +isBitAndPow2 (ast * tree) +{ + /* if this is not a bit and */ + if (!IS_BITAND (tree)) + return -1; /* will look for tree of the form - ( expr >> ((sizeof expr) -1) ) & 1 */ + ( expr & (1 << litval) */ if (!IS_AST_LIT_VALUE (tree->right)) + return -1; + + return powof2 ((TYPE_TARGET_ULONG)AST_LIT_VALUE (tree->right)); +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetHbit - get highest order bit of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetHbit (ast * tree, RESULT_TYPE resultType) +{ + int i, j; + ast * expr; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + if ((AST_LIT_VALUE (tree->right) != 1) || + ((i = (int) AST_LIT_VALUE (tree->left->right)) != + (j = (getSize (TTYPE (expr)) * 8 - 1)))) + expr = NULL; + } + if (!expr && (resultType == RESULT_TYPE_BIT)) + { + expr = tree->left; + if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1) + expr = NULL; + } + if (!expr) return tree; - if (AST_LIT_VALUE (tree->right) != 1) + /* make sure the port supports GETHBIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr)))) return tree; - if (!IS_RIGHT_OP (tree->left)) + return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE); +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetAbit - get a single bit of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetAbit (ast * tree, RESULT_TYPE resultType) +{ + ast * expr; + ast * count = NULL; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + if (AST_LIT_VALUE (tree->right) != 1) + expr = NULL; + count = tree->left->right; + } + if (!expr && (resultType == RESULT_TYPE_BIT)) + { + int p2 = isBitAndPow2 (tree); + if (p2 >= 0) + { + expr = tree->left; + count = newAst_VALUE (valueFromLit (p2)); + } + } + if (!expr) return tree; - if (!IS_AST_LIT_VALUE (tree->left->right)) + /* make sure the port supports GETABIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr)))) return tree; - if ((i = (int) AST_LIT_VALUE (tree->left->right)) != - (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) + return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE); + +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetByte - get a byte of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetByte (ast * tree, RESULT_TYPE resultType) +{ + unsigned int i = 0; + ast * expr; + ast * count = NULL; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + i = (unsigned int) AST_LIT_VALUE (tree->left->right); + count = tree->left->right; + if (AST_LIT_VALUE (tree->right) != 0xFF) + expr = NULL; + } + if (!expr && resultType == RESULT_TYPE_CHAR) + { + /* if this is a right shift over a multiple of 8 */ + if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right)) + { + i = (unsigned int) AST_LIT_VALUE (tree->right); + count = tree->right; + expr = tree->left; + } + } + if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8)) return tree; - - /* make sure the port supports GETHBIT */ + + /* make sure the port supports GETBYTE */ if (port->hasExtBitOp - && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) + && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr)))) return tree; - return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_TYPE_NONE); + return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE); +} +/*-----------------------------------------------------------------*/ +/* optimizeGetWord - get two bytes of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetWord (ast * tree, RESULT_TYPE resultType) +{ + unsigned int i = 0; + ast * expr; + ast * count = NULL; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + i = (unsigned int) AST_LIT_VALUE (tree->left->right); + count = tree->left->right; + if (AST_LIT_VALUE (tree->right) != 0xFFFF) + expr = NULL; + } + if (!expr && resultType == RESULT_TYPE_INT) + { + /* if this is a right shift over a multiple of 8 */ + if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right)) + { + i = (unsigned int) AST_LIT_VALUE (tree->right); + count = tree->right; + expr = tree->left; + } + } + if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8)) + return tree; + + /* make sure the port supports GETWORD */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr)))) + return tree; + + return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE); } /*-----------------------------------------------------------------*/ @@ -4889,12 +5500,12 @@ optimizeRRCRLC (ast * root) 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 the root operation is not a | operation then 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 + /* that aside let's start looking for the first case : I use a negative check a lot to improve the efficiency */ /* (?expr << 1) | (?expr >> 7) */ if (IS_LEFT_OP (root->left) && @@ -5052,7 +5663,7 @@ optimizeSWAP (ast * root) 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 the root operation is not a | operation then not */ if (!IS_BITOR (root)) return root; @@ -5096,7 +5707,7 @@ optimizeSWAP (ast * root) } /*-----------------------------------------------------------------*/ -/* optimizeCompare - otimizes compares for bit variables */ +/* optimizeCompare - optimizes compares for bit variables */ /*-----------------------------------------------------------------*/ static ast * optimizeCompare (ast * root) @@ -5216,10 +5827,11 @@ optimizeCompare (ast * root) noOptimize: return root; } + /*-----------------------------------------------------------------*/ /* addSymToBlock : adds the symbol to the first block we find */ /*-----------------------------------------------------------------*/ -void +void addSymToBlock (symbol * sym, ast * tree) { /* reached end of tree or a leaf */ @@ -5245,7 +5857,7 @@ addSymToBlock (symbol * sym, ast * tree) /*-----------------------------------------------------------------*/ /* processRegParms - do processing for register parameters */ /*-----------------------------------------------------------------*/ -static void +static void processRegParms (value * args, ast * body) { while (args) @@ -5270,6 +5882,397 @@ DEFSETFUNC (resetParmKey) return 1; } + + +/*------------------------------------------------------------------*/ +/* fixupInlineLabel - change a label in an inlined function so that */ +/* it is always unique no matter how many times */ +/* the function is inlined. */ +/*------------------------------------------------------------------*/ +static void +fixupInlineLabel (symbol * sym) +{ + char name[SDCC_NAME_MAX + 1]; + + SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count); + strcpy (sym->name, name); +} + + +/*------------------------------------------------------------------*/ +/* copyAstLoc - copy location information (file, line, block, etc.) */ +/* from one ast node to another */ +/*------------------------------------------------------------------*/ +static void +copyAstLoc (ast * dest, ast * src) +{ + dest->lineno = src->lineno; + dest->filename = src->filename; + dest->level = src->level; + dest->block = src->block; + dest->seqPoint = src->seqPoint; + +} + + +/*-----------------------------------------------------------------*/ +/* fixupInline - perform various fixups on an inline function tree */ +/* to take into account that it is no longer a */ +/* stand-alone function. */ +/*-----------------------------------------------------------------*/ +static void +fixupInline (ast * tree, int level) +{ + tree->block = currBlockno; + + if (IS_AST_OP (tree) && (tree->opval.op == BLOCK)) + { + symbol * decls; + + currBlockno++; + level++; + + /* Add any declared variables back into the symbol table */ + decls = tree->values.sym; + while (decls) + { + decls->level = level; + decls->block = currBlockno; + addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0); + decls = decls->next; + } + } + + tree->level = level; + + /* Update symbols */ + if (IS_AST_VALUE (tree) && + tree->opval.val->sym) + { + symbol * sym = tree->opval.val->sym; + + sym->level = level; + sym->block = currBlockno; + + /* If the symbol is a label, we need to renumber it */ + if (sym->islbl) + fixupInlineLabel (sym); + } + + /* Update IFX target labels */ + if (tree->type == EX_OP && tree->opval.op == IFX) + { + if (tree->trueLabel) + fixupInlineLabel (tree->trueLabel); + if (tree->falseLabel) + fixupInlineLabel (tree->falseLabel); + } + + /* Replace RETURN with optional assignment and a GOTO to the end */ + /* of the inlined function */ + if (tree->type == EX_OP && tree->opval.op == RETURN) + { + ast * assignTree = NULL; + ast * gotoTree; + + if (inlineState.retsym && tree->right) + { + assignTree = newNode ('=', + newAst_VALUE (symbolVal (inlineState.retsym)), + tree->right); + copyAstLoc (assignTree, tree); + } + + gotoTree = newNode (GOTO, + newAst_VALUE (symbolVal (inlineState.retlab)), + NULL); + copyAstLoc (gotoTree, tree); + + tree->opval.op = NULLOP; + tree->left = assignTree; + tree->right = gotoTree; + } + + /* Update any children */ + if (tree->left) + fixupInline (tree->left, level); + if (tree->right) + fixupInline (tree->right, level); + + if (IS_AST_OP (tree) && (tree->opval.op == LABEL)) + { + symbol * label = tree->left->opval.val->sym; + + label->key = labelKey++; + /* Add this label back into the symbol table */ + addSym (LabelTab, label, label->name, label->level, 0, 0); + } + + + if (IS_AST_OP (tree) && (tree->opval.op == BLOCK)) + { + level--; + } +} + +/*-----------------------------------------------------------------*/ +/* inlineAddDecl - add a variable declaration to an ast block. It */ +/* is also added to the symbol table if addSymTab */ +/* is nonzero. */ +/*-----------------------------------------------------------------*/ +static void +inlineAddDecl (symbol * sym, ast * block, int addSymTab) +{ + if (block != NULL) + { + symbol **decl = &(block->values.sym); + + sym->level = block->level; + sym->block = block->block; + + while (*decl) + { + if (strcmp ((*decl)->name, sym->name) == 0) + return; + decl = &( (*decl)->next ); + } + + *decl = sym; + + if (addSymTab) + addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0); + + } +} + + +/*-----------------------------------------------------------------*/ +/* inlineTempVar - create a temporary variable for inlining */ +/*-----------------------------------------------------------------*/ +static symbol * +inlineTempVar (sym_link * type, int level) +{ + symbol * sym; + + sym = newSymbol (genSymName(level), level ); + sym->type = copyLinkChain (type); + sym->etype = getSpec(sym->type); + SPEC_SCLS (sym->etype) = S_AUTO; + SPEC_OCLS (sym->etype) = NULL; + SPEC_EXTR (sym->etype) = 0; + SPEC_STAT (sym->etype) = 0; + if IS_SPEC (sym->type) + SPEC_VOLATILE (sym->type) = 0; + else + DCL_PTR_VOLATILE (sym->type) = 0; + SPEC_ABSA (sym->etype) = 0; + + return sym; +} + + +/*-----------------------------------------------------------------*/ +/* inlineFindParmRecurse - recursive function for inlineFindParm */ +/*-----------------------------------------------------------------*/ +static ast * +inlineFindParmRecurse (ast * parms, int *index) +{ + if (!parms) + return NULL; + + if (parms->type == EX_OP && parms->opval.op == PARAM) + { + ast * p; + + p=inlineFindParmRecurse (parms->left, index); + if (p) + return p; + p=inlineFindParmRecurse (parms->right, index); + if (p) + return p; + } + if (!*index) + return parms; + (*index)--; + return NULL; +} + + +/*-----------------------------------------------------------------*/ +/* inlineFindParm - search an ast tree of parameters to find one */ +/* at a particular index (0=first parameter). */ +/* Returns NULL if not found. */ +/*-----------------------------------------------------------------*/ +static ast * +inlineFindParm (ast * parms, int index) +{ + return inlineFindParmRecurse (parms, &index); +} + + +/*-----------------------------------------------------------------*/ +/* expandInlineFuncs - replace calls to inline functions with the */ +/* function itself */ +/*-----------------------------------------------------------------*/ +static void +expandInlineFuncs (ast * tree, ast * block) +{ + if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left + && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym) + { + symbol * func = tree->left->opval.val->sym; + symbol * csym; + + /* The symbol is probably not bound yet, so find the real one */ + csym = findSymWithLevel (SymbolTab, func); + if (csym) + func = csym; + + /* Is this an inline function that we can inline? */ + if (IFFUNC_ISINLINE (func->type) && func->funcTree) + { + symbol * retsym = NULL; + symbol * retlab; + ast * inlinetree; + ast * inlinetree2; + ast * temptree; + value * args; + int argIndex; + + /* Generate a label for the inlined function to branch to */ + /* in case it contains a return statement */ + retlab = newSymbol (genSymName(tree->level+1), tree->level+1 ); + retlab->isitmp = 1; + retlab->islbl = 1; + inlineState.retlab = retlab; + + /* Build the subtree for the inlined function in the form: */ + /* { //inlinetree block */ + /* { //inlinetree2 block */ + /* inline_function_code; */ + /* retlab: */ + /* } */ + /* } */ + temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL); + copyAstLoc (temptree, tree); + temptree = newNode (NULLOP, copyAst (func->funcTree), temptree); + copyAstLoc (temptree, tree); + temptree = newNode (BLOCK, NULL, temptree); + copyAstLoc (temptree, tree); + inlinetree2 = temptree; + inlinetree = newNode (BLOCK, NULL, inlinetree2); + copyAstLoc (inlinetree, tree); + + /* To pass parameters to the inlined function, we need some */ + /* intermediate variables. This avoids scoping problems */ + /* when the parameter declaration names are used differently */ + /* during the function call. For example, a function */ + /* declared as func(int x, int y) but called as func(y,x). */ + /* { //inlinetree block */ + /* type1 temparg1; */ + /* ... */ + /* typen tempargn; */ + /* temparg1 = argument1; */ + /* ... */ + /* tempargn = argumentn; */ + /* { //inlinetree2 block */ + /* type1 param1; */ + /* ... */ + /* typen paramn; */ + /* param1 = temparg1; */ + /* ... */ + /* paramn = tempargn; */ + /* inline_function_code; */ + /* retlab: */ + /* } */ + /* } */ + args = FUNC_ARGS (func->type); + argIndex = 0; + while (args) + { + symbol * temparg; + ast * passedarg; + ast * assigntree; + symbol * parm = copySymbol (args->sym); + + temparg = inlineTempVar (args->sym->type, tree->level+1); + inlineAddDecl (temparg, inlinetree, FALSE); + + passedarg = inlineFindParm (tree->right, argIndex); + assigntree = newNode ('=', + newAst_VALUE (symbolVal (temparg)), + passedarg); + inlinetree->right = newNode (NULLOP, + assigntree, + inlinetree->right); + + inlineAddDecl (parm, inlinetree2, FALSE); + parm->_isparm = 0; + + assigntree = newNode ('=', + newAst_VALUE (symbolVal (parm)), + newAst_VALUE (symbolVal (temparg))); + inlinetree2->right = newNode (NULLOP, + assigntree, + inlinetree2->right); + + + args = args->next; + argIndex++; + } + + /* Handle the return type */ + if (!IS_VOID (func->type->next)) + { + /* Create a temporary symbol to hold the return value and */ + /* join it with the inlined function using the comma */ + /* operator. The fixupInline function will take care of */ + /* changing return statements into assignments to retsym. */ + /* (parameter passing and return label omitted for clarity) */ + /* rettype retsym; */ + /* ... */ + /* {{inline_function_code}}, retsym */ + + retsym = inlineTempVar (func->type->next, tree->level); + inlineAddDecl (retsym, block, TRUE); + + tree->opval.op = ','; + tree->left = inlinetree; + tree->right = newAst_VALUE (symbolVal (retsym)); + } + else + { + tree->opval.op = NULLOP; + tree->left = NULL; + tree->right = inlinetree; + } + inlineState.retsym = retsym; + + /* Renumber the various internal counters on the inlined */ + /* function's tree nodes and symbols. Add the inlined */ + /* function's local variables to the appropriate scope(s). */ + /* Convert inlined return statements to an assignment to */ + /* retsym (if needed) and a goto retlab. */ + fixupInline (inlinetree, inlinetree->level); + inlineState.count++; + } + + } + + /* Recursively continue to search for functions to inline. */ + if (IS_AST_OP (tree)) + { + if (tree->opval.op == BLOCK) + block = tree; + + if (tree->left) + expandInlineFuncs (tree->left, block); + if (tree->right) + expandInlineFuncs (tree->right, block); + } +} + + /*-----------------------------------------------------------------*/ /* createFunction - This is the key node that calls the iCode for */ /* generating the code for a function. Note code */ @@ -5313,15 +6316,15 @@ createFunction (symbol * name, ast * body) } else { - addSymChain (name); + addSymChain (&name); allocVariables (name); } - name->lastLine = mylineno; + name->lastLine = lexLineno; currFunc = name; /* set the stack pointer */ stackPtr = -port->stack.direction * port->stack.call_overhead; - xstackPtr = -port->stack.direction * port->stack.call_overhead; + xstackPtr = 0; if (IFFUNC_ISISR (name->type)) stackPtr -= port->stack.direction * port->stack.isr_overhead; @@ -5339,6 +6342,12 @@ createFunction (symbol * name, ast * body) if (IFFUNC_ISREENT (name->type)) reentrant++; + inlineState.count = 0; + expandInlineFuncs (body, NULL); + + if (FUNC_ISINLINE (name->type)) + name->funcTree = copyAst (body); + allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */ /* do processing for parameters that are passed in registers */ @@ -5348,43 +6357,44 @@ createFunction (symbol * name, ast * body) stackPtr = 0; xstackPtr = -1; + gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */ + /* 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 */ SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name); body = resolveSymbols (body); /* resolve the symbols */ body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */ - + + /* save the stack information */ + if (options.useXstack) + name->xstack = SPEC_STAK (fetype) = stack; + else + name->stack = SPEC_STAK (fetype) = stack; 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 (options.dump_tree) + PA(ex); if (fatalError) - { - werror (E_FUNC_NO_CODE, name->name); - goto skipall; - } + goto skipall; + + /* Do not generate code for inline functions unless extern also */ + if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype)) + goto skipall; /* create the node & generate intermediate code */ GcurMemmap = code; - codeOutFile = code->oFile; + codeOutBuf = &code->oBuf; piCode = iCodeFromAst (ex); + name->generated = 1; if (fatalError) - { - werror (E_FUNC_NO_CODE, name->name); - goto skipall; - } + goto skipall; eBBlockFromiCode (piCode); @@ -5392,7 +6402,7 @@ createFunction (symbol * name, ast * body) if (staticAutos) { GcurMemmap = statsg; - codeOutFile = statsg->oFile; + codeOutBuf = &statsg->oBuf; eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE))); staticAutos = NULL; } @@ -5429,7 +6439,7 @@ skipall: } -#define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); } +#define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); } /*-----------------------------------------------------------------*/ /* ast_print : prints the ast (for debugging purposes) */ /*-----------------------------------------------------------------*/ @@ -5437,713 +6447,732 @@ skipall: 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->left->opval.val->type->next,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+2,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+2); - INDENT(indent,outfile); - fprintf(outfile,"}\n"); - return; - } - if (tree->opval.op == NULLOP) { - ast_print(tree->left,outfile,indent); - ast_print(tree->right,outfile,indent); - return ; - } - INDENT(indent,outfile); + if (!tree) return ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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 = ", tree); - if (SPEC_USIGN (tree->opval.val->etype)) - fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val)); - else - fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val)); - fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val), - floatFromVal(tree->opval.val)); - } else if (tree->opval.val->sym) { - /* if the undefined flag is set then give error message */ - if (tree->opval.val->sym->undefined) { - 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+2); - ast_print(tree->right,outfile,indent+2); - return; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* struct/union */ - /*----------------------------*/ - case '.': - fprintf(outfile,"STRUCT_ACCESS (%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 ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - ast_print(tree->right,outfile,indent+2); - return ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* ++/-- operation */ - /*----------------------------*/ - 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); /* 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); /* postdecrement case */ - ast_print(tree->right,outfile,indent+2); /* predecrement case */ - 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+2); - ast_print(tree->right,outfile,indent+2); - } else { - fprintf(outfile,"ADDRESS_OF (%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 ; - /*----------------------------*/ - /* bitwise or */ - /*----------------------------*/ - case '|': - fprintf(outfile,"OR (%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 ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* bitwise xor */ - /*----------------------------*/ - case '^': - fprintf(outfile,"XOR (%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 ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* division */ - /*----------------------------*/ - case '/': - fprintf(outfile,"DIV (%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 ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* modulus */ - /*----------------------------*/ - case '%': - fprintf(outfile,"MOD (%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 ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - return ; - } - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* multiplication */ - /*----------------------------*/ - fprintf(outfile,"MULT (%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 ; - - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - } else { - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* addition */ - /*----------------------------*/ - fprintf(outfile,"ADD (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - } else { - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* subtraction */ - /*----------------------------*/ - fprintf(outfile,"SUB (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* compliment */ - /*----------------------------*/ - case '~': - fprintf(outfile,"COMPL (%p) type (",tree); - printTypeChain(tree->ftype,outfile); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - return ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* not */ - /*----------------------------*/ - case '!': - fprintf(outfile,"NOT (%p) type (",tree); - printTypeChain(tree->ftype,outfile); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - return ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* shift */ - /*----------------------------*/ - case RRC: - fprintf(outfile,"RRC (%p) type (",tree); - printTypeChain(tree->ftype,outfile); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - return ; - - case RLC: - fprintf(outfile,"RLC (%p) type (",tree); - printTypeChain(tree->ftype,outfile); - 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); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - return ; - case LEFT_OP: - fprintf(outfile,"LEFT_SHIFT (%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 RIGHT_OP: - fprintf(outfile,"RIGHT_SHIFT (%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 ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - return ; - - case AND_OP: - fprintf(outfile,"ANDAND (%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 OR_OP: - fprintf(outfile,"OROR (%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 ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* comparison operators */ - /*----------------------------*/ - case '>': - fprintf(outfile,"GT(>) (%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 '<': - fprintf(outfile,"LT(<) (%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 LE_OP: - fprintf(outfile,"LE(<=) (%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 GE_OP: - fprintf(outfile,"GE(>=) (%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 EQ_OP: - fprintf(outfile,"EQ(==) (%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 NE_OP: - fprintf(outfile,"NE(!=) (%p) type (",tree); - printTypeChain(tree->ftype,outfile); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - ast_print(tree->right,outfile,indent+2); - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - ast_print(tree->right,outfile,indent+2); - return; - - case ':': - fprintf(outfile,"COLON(:) (%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 ; - - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* assignment operators */ - /*----------------------------*/ - case MUL_ASSIGN: - fprintf(outfile,"MULASS(*=) (%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 DIV_ASSIGN: - fprintf(outfile,"DIVASS(/=) (%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 AND_ASSIGN: - fprintf(outfile,"ANDASS(&=) (%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 OR_ASSIGN: - 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); - printTypeChain(tree->ftype,outfile); - fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); - ast_print(tree->right,outfile,indent+2); - return; - case RIGHT_ASSIGN: - fprintf(outfile,"RSHFTASS(>>=) (%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 LEFT_ASSIGN: - fprintf(outfile,"LSHFTASS(<<=) (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* -= operator */ - /*----------------------------*/ - case SUB_ASSIGN: - fprintf(outfile,"SUBASS(-=) (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* += operator */ - /*----------------------------*/ - case ADD_ASSIGN: - fprintf(outfile,"ADDASS(+=) (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* straight assignemnt */ - /*----------------------------*/ - case '=': - fprintf(outfile,"ASSIGN(=) (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* comma operator */ - /*----------------------------*/ - case ',': - fprintf(outfile,"COMMA(,) (%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; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* 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+2); - ast_print(tree->right,outfile,indent+2); - return; - case PARAM: - fprintf(outfile,"PARMS\n"); - ast_print(tree->left,outfile,indent+2); - if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) { - ast_print(tree->right,outfile,indent+2); - } - return ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* return statement */ - /*----------------------------*/ - case RETURN: - fprintf(outfile,"RETURN (%p) type (",tree); - if (tree->right) { - printTypeChain(tree->right->ftype,outfile); - } - fprintf(outfile,")\n"); - ast_print(tree->right,outfile,indent+2); - return ; - /*------------------------------------------------------------------*/ - /*----------------------------*/ - /* label statement */ - /*----------------------------*/ - case LABEL : - fprintf(outfile,"LABEL (%p)\n",tree); - ast_print(tree->left,outfile,indent+2); - 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+2,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+2); - if (tree->trueLabel) { - INDENT(indent+2,outfile); - fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name); - } - if (tree->falseLabel) { - 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 */ - /*----------------------------*/ - case FOR: - fprintf(outfile,"FOR (%p) \n",tree); - if (AST_FOR( tree, initExpr)) { - INDENT(indent+2,outfile); - fprintf(outfile,"INIT EXPR "); - ast_print(AST_FOR(tree, initExpr),outfile,indent+2); - } - if (AST_FOR( tree, condExpr)) { - INDENT(indent+2,outfile); - fprintf(outfile,"COND EXPR "); - ast_print(AST_FOR(tree, condExpr),outfile,indent+2); - } - if (AST_FOR( tree, loopExpr)) { - INDENT(indent+2,outfile); - fprintf(outfile,"LOOP EXPR "); - ast_print(AST_FOR(tree, loopExpr),outfile,indent+2); - } - 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 ; - } + /* 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->left->opval.val->type->next,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+2,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+2); + INDENT(indent,outfile); + fprintf(outfile,"}\n"); + return; + } + if (tree->opval.op == NULLOP) { + ast_print(tree->left,outfile,indent); + 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 = ", tree); + if (SPEC_USIGN (tree->opval.val->etype)) + fprintf(outfile,"%u", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val)); + else + fprintf(outfile,"%d", (TYPE_TARGET_LONG) floatFromVal(tree->opval.val)); + fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) 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 @ %p)", + tree->opval.val->sym->name, tree, tree->opval.val->sym); + } + 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+2); + ast_print(tree->right,outfile,indent+2); + return; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* struct/union */ + /*----------------------------*/ + case '.': + fprintf(outfile,"STRUCT_ACCESS (%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 ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + ast_print(tree->right,outfile,indent+2); + return ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* ++/-- operation */ + /*----------------------------*/ + 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); /* 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); /* postdecrement case */ + ast_print(tree->right,outfile,indent+2); /* predecrement case */ + 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+2); + ast_print(tree->right,outfile,indent+2); + } else { + fprintf(outfile,"ADDRESS_OF (%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 ; + /*----------------------------*/ + /* bitwise or */ + /*----------------------------*/ + case '|': + fprintf(outfile,"OR (%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 ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* bitwise xor */ + /*----------------------------*/ + case '^': + fprintf(outfile,"XOR (%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 ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* division */ + /*----------------------------*/ + case '/': + fprintf(outfile,"DIV (%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 ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* modulus */ + /*----------------------------*/ + case '%': + fprintf(outfile,"MOD (%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 ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + return ; + } + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* multiplication */ + /*----------------------------*/ + fprintf(outfile,"MULT (%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 ; + + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + } else { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* addition */ + /*----------------------------*/ + fprintf(outfile,"ADD (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + } else { + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* subtraction */ + /*----------------------------*/ + fprintf(outfile,"SUB (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* complement */ + /*----------------------------*/ + case '~': + fprintf(outfile,"COMPL (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* not */ + /*----------------------------*/ + case '!': + fprintf(outfile,"NOT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* shift */ + /*----------------------------*/ + case RRC: + fprintf(outfile,"RRC (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; + + case RLC: + fprintf(outfile,"RLC (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + 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); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; + case GETABIT: + fprintf(outfile,"GETABIT (%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 GETBYTE: + fprintf(outfile,"GETBYTE (%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 GETWORD: + fprintf(outfile,"GETWORD (%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 LEFT_OP: + fprintf(outfile,"LEFT_SHIFT (%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 RIGHT_OP: + fprintf(outfile,"RIGHT_SHIFT (%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 ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + return ; + + case AND_OP: + fprintf(outfile,"ANDAND (%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 OR_OP: + fprintf(outfile,"OROR (%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 ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* comparison operators */ + /*----------------------------*/ + case '>': + fprintf(outfile,"GT(>) (%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 '<': + fprintf(outfile,"LT(<) (%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 LE_OP: + fprintf(outfile,"LE(<=) (%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 GE_OP: + fprintf(outfile,"GE(>=) (%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 EQ_OP: + fprintf(outfile,"EQ(==) (%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 NE_OP: + fprintf(outfile,"NE(!=) (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + ast_print(tree->right,outfile,indent+2); + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + ast_print(tree->right,outfile,indent+2); + return; + + case ':': + fprintf(outfile,"COLON(:) (%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 ; + + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* assignment operators */ + /*----------------------------*/ + case MUL_ASSIGN: + fprintf(outfile,"MULASS(*=) (%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 DIV_ASSIGN: + fprintf(outfile,"DIVASS(/=) (%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 AND_ASSIGN: + fprintf(outfile,"ANDASS(&=) (%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 OR_ASSIGN: + 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); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + ast_print(tree->right,outfile,indent+2); + return; + case RIGHT_ASSIGN: + fprintf(outfile,"RSHFTASS(>>=) (%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 LEFT_ASSIGN: + fprintf(outfile,"LSHFTASS(<<=) (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* -= operator */ + /*----------------------------*/ + case SUB_ASSIGN: + fprintf(outfile,"SUBASS(-=) (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* += operator */ + /*----------------------------*/ + case ADD_ASSIGN: + fprintf(outfile,"ADDASS(+=) (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* straight assignemnt */ + /*----------------------------*/ + case '=': + fprintf(outfile,"ASSIGN(=) (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* comma operator */ + /*----------------------------*/ + case ',': + fprintf(outfile,"COMMA(,) (%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; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* 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+2); + ast_print(tree->right,outfile,indent+2); + return; + case PARAM: + fprintf(outfile,"PARMS\n"); + ast_print(tree->left,outfile,indent+2); + if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) { + ast_print(tree->right,outfile,indent+2); + } + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* return statement */ + /*----------------------------*/ + case RETURN: + fprintf(outfile,"RETURN (%p) type (",tree); + if (tree->right) { + printTypeChain(tree->right->ftype,outfile); + } + fprintf(outfile,")\n"); + ast_print(tree->right,outfile,indent+2); + return ; + /*------------------------------------------------------------------*/ + /*----------------------------*/ + /* label statement */ + /*----------------------------*/ + case LABEL : + fprintf(outfile,"LABEL (%p)\n",tree); + ast_print(tree->left,outfile,indent+2); + 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+2,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+2); + if (tree->trueLabel) { + INDENT(indent+2,outfile); + fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name); + } + if (tree->falseLabel) { + 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 */ + /*----------------------------*/ + case FOR: + fprintf(outfile,"FOR (%p) \n",tree); + if (AST_FOR( tree, initExpr)) { + INDENT(indent+2,outfile); + fprintf(outfile,"INIT EXPR "); + ast_print(AST_FOR(tree, initExpr),outfile,indent+2); + } + if (AST_FOR( tree, condExpr)) { + INDENT(indent+2,outfile); + fprintf(outfile,"COND EXPR "); + ast_print(AST_FOR(tree, condExpr),outfile,indent+2); + } + if (AST_FOR( tree, loopExpr)) { + INDENT(indent+2,outfile); + fprintf(outfile,"LOOP EXPR "); + ast_print(AST_FOR(tree, loopExpr),outfile,indent+2); + } + 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 ; + } } void PA(ast *t) { - ast_print(t,stdout,0); + ast_print(t,stdout,0); } - - /*-----------------------------------------------------------------*/ /* astErrors : returns non-zero if errors present in tree */ /*-----------------------------------------------------------------*/ int astErrors(ast *t) { int errors=0; - + if (t) { if (t->isError) errors++; - + if (t->type == EX_VALUE && t->opval.val->sym && t->opval.val->sym->undefined) @@ -6152,6 +7181,6 @@ int astErrors(ast *t) errors += astErrors(t->left); errors += astErrors(t->right); } - + return errors; }