X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCast.c;h=354a70b2e99e0dbed33c6c9ddf7594e1ebe3f3f2;hb=c34cf61917860a821a4631edda334443633805e7;hp=1399fbd8b2ffa2fbcafed208873de860c078ef59;hpb=28a737dd5ef9959b63ee66d2f069891649a97c76;p=fw%2Fsdcc diff --git a/src/SDCCast.c b/src/SDCCast.c index 1399fbd8..354a70b2 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -52,6 +52,7 @@ static ast *createIval (ast *, sym_link *, initList *, ast *); static ast *createIvalCharPtr (ast *, sym_link *, ast *); static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); +ast *optimizeSWAP (ast *); ast *optimizeGetHbit (ast *); ast *backPatchLabels (ast *, symbol *, symbol *); void PA(ast *t); @@ -159,7 +160,7 @@ newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel) /*-----------------------------------------------------------------*/ /* copyAstValues - copies value portion of ast if needed */ /*-----------------------------------------------------------------*/ -void +void copyAstValues (ast * dest, ast * src) { switch (src->opval.op) @@ -184,7 +185,7 @@ copyAstValues (ast * dest, ast * src) case ARRAYINIT: dest->values.constlist = copyLiteralList(src->values.constlist); break; - + case FOR: AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel)); AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel)); @@ -201,7 +202,7 @@ copyAstValues (ast * dest, ast * src) /* copyAst - makes a copy of a given astession */ /*-----------------------------------------------------------------*/ ast * -copyAst (ast * src) +copyAst (ast * src) { ast *dest; @@ -258,24 +259,24 @@ ast *removeIncDecOps (ast * tree) { if (!tree) return NULL; - if (tree->type == EX_OP && + if (tree->type == EX_OP && (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) { if (tree->left) tree=tree->left; - else + else tree=tree->right; } tree->left=removeIncDecOps(tree->left); tree->right=removeIncDecOps(tree->right); - + return tree; } /*-----------------------------------------------------------------*/ /* hasSEFcalls - returns TRUE if tree has a function call */ /*-----------------------------------------------------------------*/ -bool +bool hasSEFcalls (ast * tree) { if (!tree) @@ -555,7 +556,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) args = args->next = newValue (); } } - + /* save it */ addSymChain (sym); sym->cdef = 1; @@ -567,7 +568,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes) /*-----------------------------------------------------------------*/ /* reverseParms - will reverse a parameter tree */ /*-----------------------------------------------------------------*/ -static void +static void reverseParms (ast * ptree) { ast *ttree; @@ -658,7 +659,7 @@ processParms (ast * func, if (IS_INTEGRAL (ftype) && (getSize (ftype) < (unsigned) INTSIZE)) { - if (IS_AST_OP(actParm) && + if (IS_AST_OP(actParm) && (actParm->opval.op == LEFT_OP || actParm->opval.op == '*' || actParm->opval.op == '+' || @@ -1015,7 +1016,7 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* if type is SPECIFIER */ if (IS_SPEC (type)) rast = createIvalType (sym, type, ilist); - + if (wid) return decorateType (resolveSymbols (newNode (NULLOP, wid, rast))); else @@ -1220,6 +1221,7 @@ processBlockVars (ast * tree, int *stack, int action) return tree; } + /*-------------------------------------------------------------*/ /* constExprTree - returns TRUE if this tree is a constant */ /* expression */ @@ -1231,7 +1233,7 @@ bool constExprTree (ast *cexpr) { } cexpr = decorateType (resolveSymbols (cexpr)); - + switch (cexpr->type) { case EX_VALUE: @@ -1251,6 +1253,7 @@ bool constExprTree (ast *cexpr) { IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) { // a symbol in code space will never change // This is only for the 'char *s="hallo"' case and will have to leave + //printf(" code space symbol"); return TRUE; } return FALSE; @@ -1279,11 +1282,12 @@ bool constExprTree (ast *cexpr) { if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) { return TRUE; } + return FALSE; case EX_OPERAND: return IS_CONSTANT(operandType(cexpr->opval.oprnd)); } return FALSE; -} +} /*-----------------------------------------------------------------*/ /* constExprValue - returns the value of a constant expression */ @@ -1316,11 +1320,15 @@ constExprValue (ast * cexpr, int check) if (IS_AST_OP (cexpr) && cexpr->opval.op == CAST && IS_LITERAL (cexpr->right->ftype)) + { return valCastLiteral (cexpr->ftype, floatFromVal (cexpr->right->opval.val)); + } if (IS_AST_VALUE (cexpr)) + { return cexpr->opval.val; + } if (check) werror (E_CONST_EXPECTED, "found expression"); @@ -1589,7 +1597,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) return TRUE; /*------------------------------------------------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: case DEC_OP: /* sure we are not sym is not modified */ @@ -1657,6 +1665,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case RRC: case RLC: case GETHBIT: + case SWAP: if (IS_AST_SYM_VALUE (pbody->left) && isSymbolEqual (AST_SYMBOL (pbody->left), sym)) return FALSE; @@ -1675,6 +1684,14 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case '?': case ':': case SIZEOF: /* evaluate wihout code generation */ + + if (IS_AST_SYM_VALUE (pbody->left) && + isSymbolEqual (AST_SYMBOL (pbody->left), sym)) + return FALSE; + + if (IS_AST_SYM_VALUE (pbody->right) && + isSymbolEqual (AST_SYMBOL (pbody->right), sym)) + return FALSE; return isConformingBody (pbody->left, sym, body) && isConformingBody (pbody->right, sym, body); @@ -1696,7 +1713,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) return FALSE; // if the loopvar is used in another (maybe conditional) block if (astHasSymbol (pbody->right, sym) && - (pbody->level > body->level)) { + (pbody->level >= body->level)) { return FALSE; } } @@ -1770,7 +1787,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) /* if the for loop is reversible. If yes will set the value of */ /* the loop control var & init value & termination value */ /*-----------------------------------------------------------------*/ -bool +bool isLoopReversible (ast * loop, symbol ** loopCntrl, ast ** init, ast ** end) { @@ -1854,10 +1871,10 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) newNode ('=', newAst_VALUE (symbolVal (sym)), end)); - + replLoopSym (loop->left, sym); setAstLineno (rloop, init->lineno); - + rloop = newNode (NULLOP, newNode ('=', newAst_VALUE (symbolVal (sym)), @@ -1870,14 +1887,63 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) newAst_VALUE (symbolVal (sym)), newAst_VALUE (constVal ("1"))), rloop)))); - + rloop->lineno=init->lineno; return decorateType (rloop); - + +} + +/*-----------------------------------------------------------------*/ +/* searchLitOp - search tree (*ops only) for an ast with literal */ +/*-----------------------------------------------------------------*/ +static ast * +searchLitOp (ast *tree, ast **parent, const char *ops) +{ + ast *ret; + + if (tree && optimize.global_cse) + { + /* is there a literal operand? */ + if (tree->right && + IS_AST_OP(tree->right) && + tree->right->right && + (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1])) + { + if (IS_LITERAL (RTYPE (tree->right)) ^ + IS_LITERAL (LTYPE (tree->right))) + { + tree->right->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->right; + } + ret = searchLitOp (tree->right, parent, ops); + if (ret) + return ret; + } + if (tree->left && + IS_AST_OP(tree->left) && + tree->left->right && + (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1])) + { + if (IS_LITERAL (RTYPE (tree->left)) ^ + IS_LITERAL (LTYPE (tree->left))) + { + tree->left->decorated = 0; + tree->decorated = 0; + *parent = tree; + return tree->left; + } + ret = searchLitOp (tree->left, parent, ops); + if (ret) + return ret; + } + } + return NULL; } /*-----------------------------------------------------------------*/ -/* decorateType - compute type for this tree also does type cheking */ +/* decorateType - compute type for this tree also does type checking */ /* this is done bottom up, since type have to flow upwards */ /* it also does constant folding, and paramater checking */ /*-----------------------------------------------------------------*/ @@ -1992,11 +2058,13 @@ decorateType (ast * tree) tree->left = dtl; if (dtr != tree->right) tree->right = dtr; + if ((dtl && dtl->isError) || (dtr && dtr->isError)) + return tree; if (IS_AST_OP(tree) && (tree->opval.op == CAST || tree->opval.op == '=') && (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) && - (getSize(RTYPE(tree)) < INTSIZE)) { + (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) { // this is a cast/assign to a bigger type if (IS_AST_OP(tree->right) && IS_INTEGRAL(tree->right->ftype) && @@ -2055,9 +2123,6 @@ decorateType (ast * tree) } RRVAL (tree) = 1; COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next); - if (IS_PTR(LTYPE(tree))) { - SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); - } return tree; /*------------------------------------------------------------------*/ @@ -2103,6 +2168,7 @@ decorateType (ast * tree) /* adjust the storage class */ switch (DCL_TYPE(tree->left->ftype)) { case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; break; case FPOINTER: SPEC_SCLS(TETYPE(tree)) = S_XDATA; @@ -2111,6 +2177,7 @@ decorateType (ast * tree) SPEC_SCLS(TETYPE(tree)) = S_CODE; break; case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; break; case PPOINTER: SPEC_SCLS(TETYPE(tree)) = S_XSTACK; @@ -2122,10 +2189,45 @@ decorateType (ast * tree) SPEC_SCLS(TETYPE(tree)) = S_EEPROM; break; case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; case ARRAY: case FUNCTION: break; } + + if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left) + && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype)) + { + /* If defined struct type at addr var + then rewrite (&struct var)->member + as temp + and define membertype at (addr+offsetof(struct var,member)) temp + */ + symbol *sym; + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)), + AST_SYMBOL(tree->right)); + + sym = newSymbol(genSymName (0), 0); + sym->type = TTYPE (tree); + sym->etype = getSpec(sym->type); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype) + + element->offset; + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + AST_VALUE (tree) = symbolVal(sym); + TLVAL (tree) = 1; + TRVAL (tree) = 0; + tree->type = EX_VALUE; + tree->left = NULL; + tree->right = NULL; + } return tree; @@ -2133,12 +2235,12 @@ decorateType (ast * tree) /*----------------------------*/ /* ++/-- operation */ /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: case DEC_OP: { sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree)); COPYTYPE (TTYPE (tree), TETYPE (tree), ltc); - if (!tree->initMode && IS_CONSTANT(TETYPE(tree))) + if (!tree->initMode && IS_CONSTANT(TTYPE(tree))) werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--"); if (tree->right) @@ -2194,6 +2296,31 @@ decorateType (ast * tree) computeType (LTYPE (tree), RTYPE (tree)); TETYPE (tree) = getSpec (TTYPE (tree)); + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a and-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "&"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; return tree; } @@ -2234,10 +2361,7 @@ decorateType (ast * tree) goto errorTreeReturn; } if (SPEC_SCLS (tree->left->etype) == S_CODE) - { - DCL_TYPE (p) = CPOINTER; - DCL_PTR_CONST (p) = port->mem.code_ro; - } + DCL_TYPE (p) = CPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XDATA) DCL_TYPE (p) = FPOINTER; else if (SPEC_SCLS (tree->left->etype) == S_XSTACK) @@ -2260,10 +2384,24 @@ decorateType (ast * tree) p->next = LTYPE (tree); TTYPE (tree) = p; TETYPE (tree) = getSpec (TTYPE (tree)); - DCL_PTR_CONST (p) = SPEC_CONST (TETYPE (tree)); - DCL_PTR_VOLATILE (p) = SPEC_VOLATILE (TETYPE (tree)); LLVAL (tree) = 1; TLVAL (tree) = 1; + + #if 0 + if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP + && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left)) + { + symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)), + AST_SYMBOL(tree->left->right)); + AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left), + valueFromLit(element->offset)); + tree->left = NULL; + tree->right = NULL; + tree->type = EX_VALUE; + tree->values.literalFromCast = 1; + } + #endif + return tree; /*------------------------------------------------------------------*/ @@ -2276,8 +2414,38 @@ decorateType (ast * tree) ast *wtree = optimizeRRCRLC (tree); if (wtree != tree) return decorateType (wtree); + + wtree = optimizeSWAP (tree); + if (wtree != tree) + return decorateType (wtree); + // fall through } + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a or-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "|"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in tTree are literal now */ + decorateType (parent); + } + } /*------------------------------------------------------------------*/ /*----------------------------*/ /* bitwise xor */ @@ -2307,6 +2475,32 @@ decorateType (ast * tree) TTYPE (tree) = tree->opval.val->type; return tree; } + + /* if left is a literal exchange left & right */ + if (IS_LITERAL (LTYPE (tree))) + { + ast *tTree = tree->left; + tree->left = tree->right; + tree->right = tTree; + } + + /* if right is a literal and */ + /* we can find a 2nd literal in a xor-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "^"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), @@ -2334,10 +2528,43 @@ decorateType (ast * tree) tree->opval.val->type); return tree; } + LRVAL (tree) = RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree))); + + /* if right is a literal and */ + /* left is also a division by a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "/"); + if (litTree) + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_div */ + litTree->right = newNode ('*', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("1"); + decorateType (parent); + } + else + { + /* litTree->left is literal: no gcse possible. + We can't call decorateType(parent), because + this would cause an infinit loop. */ + parent->decorated = 1; + decorateType (litTree); + } + } + } + return tree; /*------------------------------------------------------------------*/ @@ -2391,9 +2618,43 @@ decorateType (ast * tree) werror (E_LVALUE_REQUIRED, "pointer deref"); goto errorTreeReturn; } - TTYPE (tree) = copyLinkChain (LTYPE (tree)->next); - TETYPE (tree) = getSpec (TTYPE (tree)); - SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree)); + if (IS_ADDRESS_OF_OP(tree->left)) + { + /* replace *&obj with obj */ + return tree->left->left; + } + TTYPE (tree) = copyLinkChain (LTYPE (tree)->next); + TETYPE (tree) = getSpec (TTYPE (tree)); + /* adjust the storage class */ + switch (DCL_TYPE(tree->left->ftype)) { + case POINTER: + SPEC_SCLS(TETYPE(tree)) = S_DATA; + break; + case FPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XDATA; + break; + case CPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_CODE; + break; + case GPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case PPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_XSTACK; + break; + case IPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_IDATA; + break; + case EEPPOINTER: + SPEC_SCLS(TETYPE(tree)) = S_EEPROM; + break; + case UPOINTER: + SPEC_SCLS (TETYPE (tree)) = 0; + break; + case ARRAY: + case FUNCTION: + break; + } return tree; } @@ -2428,6 +2689,23 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* we can find a 2nd literal in a mul-tree then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *parent; + ast *litTree = searchLitOp (tree, &parent, "*"); + if (litTree) + { + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + /* both operands in litTree are literal now */ + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), @@ -2520,6 +2798,46 @@ decorateType (ast * tree) tree->right = tTree; } + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree))) + { + ast *litTree, *parent; + litTree = searchLitOp (tree, &parent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_aa */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tree->left; + tree->left = tTree; + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_asr */ + ast *tTree = litTree->left; + litTree->left = tree->right; + tree->right = tTree; + } + else + { + /* foo_asl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + litTree->opval.op = '+'; + tree->opval.op = '-'; + } + } + decorateType (parent); + } + } + LRVAL (tree) = RRVAL (tree) = 1; /* if the left is a pointer */ if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) ) @@ -2628,12 +2946,54 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree))); + LRVAL (tree) = RRVAL (tree) = 1; + + /* if right is a literal and */ + /* left is also an addition/subtraction with a literal then */ + /* rearrange the tree */ + if (IS_LITERAL (RTYPE (tree)) + /* avoid infinite loop */ + && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0) + { + ast *litTree, *litParent; + litTree = searchLitOp (tree, &litParent, "+-"); + if (litTree) + { + if (litTree->opval.op == '+') + { + /* foo_sa */ + litTree->right = newNode ('-', litTree->right, tree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else if (litTree->opval.op == '-') + { + if (IS_LITERAL (RTYPE (litTree))) + { + /* foo_ssr */ + litTree->right = newNode ('+', tree->right, litTree->right); + litTree->right->lineno = tree->lineno; + + tree->right->opval.val = constVal ("0"); + } + else + { + /* foo_ssl */ + ast *tTree = litTree->right; + litTree->right = tree->right; + tree->right = tTree; + } + } + decorateType (litParent); + } + } return tree; /*------------------------------------------------------------------*/ /*----------------------------*/ - /* compliment */ + /* complement */ /*----------------------------*/ case '~': /* can be only integral type */ @@ -2689,6 +3049,7 @@ decorateType (ast * tree) /*----------------------------*/ case RRC: case RLC: + case SWAP: TTYPE (tree) = LTYPE (tree); TETYPE (tree) = LETYPE (tree); return tree; @@ -2743,14 +3104,9 @@ decorateType (ast * tree) } } LRVAL (tree) = RRVAL (tree) = 1; - if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree))) - { - COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree)); - } - else - { - COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)); - } + TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree)); + if (IS_LITERAL (TTYPE (tree))) + SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL; return tree; /*------------------------------------------------------------------*/ @@ -2764,7 +3120,7 @@ decorateType (ast * tree) werror (E_CAST_ILLEGAL); goto errorTreeReturn; } - + /* make sure the type is complete and sane */ checkTypeSanity(LETYPE(tree), "(cast)"); @@ -2780,10 +3136,10 @@ decorateType (ast * tree) tree->right = NULL; TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && + } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ { sym_link *rest = LTYPE(tree)->next; - werror(W_LITERAL_GENERIC); + werror(W_LITERAL_GENERIC); TTYPE(tree) = newLink(DECLARATOR); DCL_TYPE(TTYPE(tree)) = FPOINTER; TTYPE(tree)->next = rest; @@ -2802,27 +3158,115 @@ decorateType (ast * tree) /* if pointer to struct then check names */ if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) && IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) && - strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) + strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) { werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag, SPEC_STRUCT(LETYPE(tree))->tag); } #endif - /* if the right is a literal replace the tree */ - if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree))) { - tree->type = EX_VALUE; + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_SYM_VALUE (tree->right->left) + && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) { + + tree->type = EX_VALUE; tree->opval.val = valCastLiteral (LTYPE (tree), - floatFromVal (valFromType (RETYPE (tree)))); + SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype)); + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); tree->left = NULL; tree->right = NULL; - TTYPE (tree) = tree->opval.val->type; tree->values.literalFromCast = 1; - } else { - TTYPE (tree) = LTYPE (tree); - LRVAL (tree) = 1; + return tree; + } + + /* handle offsetof macro: */ + /* #define offsetof(TYPE, MEMBER) \ */ + /* ((unsigned) &((TYPE *)0)->MEMBER) */ + if (IS_ADDRESS_OF_OP(tree->right) + && IS_AST_OP (tree->right->left) + && tree->right->left->opval.op == PTR_OP + && IS_AST_OP (tree->right->left->left) + && tree->right->left->left->opval.op == CAST + && IS_AST_LIT_VALUE(tree->right->left->left->right)) { + + symbol *element = getStructElement ( + SPEC_STRUCT (LETYPE(tree->right->left)), + AST_SYMBOL(tree->right->left->right) + ); + + if (element) { + tree->type = EX_VALUE; + tree->opval.val = valCastLiteral ( + LTYPE (tree), + element->offset + + floatFromVal (valFromType (RETYPE (tree->right->left->left))) + ); + + TTYPE (tree) = tree->opval.val->type; + TETYPE (tree) = getSpec (TTYPE (tree)); + tree->left = NULL; + tree->right = NULL; + return tree; + } + } + + /* if the right is a literal replace the tree */ + if (IS_LITERAL (RETYPE (tree))) { + if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) { + /* rewrite (type *)litaddr + as &temp + and define type at litaddr temp + (but only if type's storage class is not generic) + */ + ast *newTree = newNode ('&', NULL, NULL); + symbol *sym; + + TTYPE (newTree) = LTYPE (tree); + TETYPE (newTree) = getSpec(LTYPE (tree)); + + /* define a global symbol at the casted address*/ + sym = newSymbol(genSymName (0), 0); + sym->type = LTYPE (tree)->next; + if (!sym->type) + sym->type = newLink (V_VOID); + sym->etype = getSpec(sym->type); + SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree)); + sym->lineDef = tree->lineno; + sym->cdef = 1; + sym->isref = 1; + SPEC_STAT (sym->etype) = 1; + SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree))); + SPEC_ABSA(sym->etype) = 1; + addSym (SymbolTab, sym, sym->name, 0, 0, 0); + allocGlobal (sym); + + newTree->left = newAst_VALUE(symbolVal(sym)); + newTree->left->lineno = tree->lineno; + LTYPE (newTree) = sym->type; + LETYPE (newTree) = sym->etype; + LLVAL (newTree) = 1; + LRVAL (newTree) = 0; + TLVAL (newTree) = 1; + return newTree; + } + if (!IS_PTR (LTYPE (tree))) { + tree->type = EX_VALUE; + tree->opval.val = + valCastLiteral (LTYPE (tree), + floatFromVal (valFromType (RETYPE (tree)))); + TTYPE (tree) = tree->opval.val->type; + tree->left = NULL; + tree->right = NULL; + tree->values.literalFromCast = 1; + TETYPE (tree) = getSpec (TTYPE (tree)); + return tree; + } } -#endif + TTYPE (tree) = LTYPE (tree); + LRVAL (tree) = 1; + +#endif TETYPE (tree) = getSpec (TTYPE (tree)); return tree; @@ -2887,7 +3331,7 @@ decorateType (ast * tree) /* if they are pointers they must be castable */ if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree))) { - if (tree->opval.op==EQ_OP && + if (tree->opval.op==EQ_OP && !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) { // we cannot cast a gptr to a !gptr: switch the leaves struct ast *s=tree->left; @@ -2993,6 +3437,9 @@ decorateType (ast * tree) case V_STRUCT: typeofv = TYPEOF_STRUCT; break; + case V_BITFIELD: + typeofv = TYPEOF_BITFIELD; + break; case V_BIT: typeofv = TYPEOF_BIT; break; @@ -3241,7 +3688,7 @@ decorateType (ast * tree) RRVAL (tree) = 1; LLVAL (tree) = 1; if (!tree->initMode ) { - if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree)))) + if (IS_CONSTANT(LTYPE(tree))) werror (E_CODE_WRITE, "="); } if (LRVAL (tree)) @@ -3941,6 +4388,11 @@ optimizeGetHbit (ast * tree) if ((i = (int) AST_LIT_VALUE (tree->left->right)) != (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) return tree; + + /* make sure the port supports GETHBIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) + return tree; return decorateType (newNode (GETHBIT, tree->left->left, NULL)); @@ -3993,6 +4445,11 @@ optimizeRRCRLC (ast * root) (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext0; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); } @@ -4023,6 +4480,11 @@ tryNext0: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext1; + /* make sure the port supports RLC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RLC, root->left->left, NULL); @@ -4054,6 +4516,11 @@ tryNext1: (getSize (TTYPE (root->left->left)) * 8 - 1)) goto tryNext2; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -4084,6 +4551,11 @@ tryNext2: (getSize (TTYPE (root->left->left)) * 8 - 1)) return root; + /* make sure the port supports RRC */ + if (port->hasExtBitOp + && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left)))) + return root; + /* whew got the first case : create the AST */ return newNode (RRC, root->left->left, NULL); @@ -4093,6 +4565,61 @@ tryNext2: return root; } +/*-----------------------------------------------------------------*/ +/* optimizeSWAP :- optimize for nibble/byte/word swaps */ +/*-----------------------------------------------------------------*/ +ast * +optimizeSWAP (ast * root) +{ + /* will look for trees of the form + (?expr << 4) | (?expr >> 4) or + (?expr >> 4) | (?expr << 4) will make that + into a SWAP : operation .. + note : by 4 I mean (number of bits required to hold the + variable /2 ) */ + /* if the root operations is not a | operation the not */ + if (!IS_BITOR (root)) + return root; + + /* (?expr << 4) | (?expr >> 4) */ + if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right)) + || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right))) + { + + if (!SPEC_USIGN (TETYPE (root->left->left))) + return root; + + if (!IS_AST_LIT_VALUE (root->left->right) || + !IS_AST_LIT_VALUE (root->right->right)) + return root; + + /* make sure it is the same expression */ + if (!isAstEqual (root->left->left, + root->right->left)) + return root; + + if (AST_LIT_VALUE (root->left->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + if (AST_LIT_VALUE (root->right->right) != + (getSize (TTYPE (root->left->left)) * 4)) + return root; + + /* make sure the port supports SWAP */ + if (port->hasExtBitOp + && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left)))) + return root; + + /* found it : create the AST */ + return newNode (SWAP, root->left->left, NULL); + } + + + /* not found return root */ + return root; +} + /*-----------------------------------------------------------------*/ /* optimizeCompare - otimizes compares for bit variables */ /*-----------------------------------------------------------------*/ @@ -4408,7 +4935,7 @@ skipall: addSet (&operKeyReset, name); applyToSet (operKeyReset, resetParmKey); - if (options.debug) + if (options.debug) cdbStructBlock(1); cleanUpLevel (LabelTab, 0); @@ -4428,7 +4955,7 @@ skipall: void ast_print (ast * tree, FILE *outfile, int indent) { - + if (!tree) return ; /* can print only decorated trees */ @@ -4441,7 +4968,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"ERROR_NODE(%p)\n",tree); } - + /* print the line */ /* if not block & function */ if (tree->type == EX_OP && @@ -4449,11 +4976,11 @@ void ast_print (ast * tree, FILE *outfile, int indent) tree->opval.op != BLOCK && tree->opval.op != NULLOP)) { } - + if (tree->opval.op == FUNCTION) { int arg=0; value *args=FUNC_ARGS(tree->left->opval.val->type); - fprintf(outfile,"FUNCTION (%s=%p) type (", + fprintf(outfile,"FUNCTION (%s=%p) type (", tree->left->opval.val->name, tree); printTypeChain (tree->left->opval.val->type->next,outfile); fprintf(outfile,") args ("); @@ -4480,8 +5007,8 @@ void ast_print (ast * tree, FILE *outfile, int indent) decls->name, decls); printTypeChain(decls->type,outfile); fprintf(outfile,")\n"); - - decls = decls->next; + + decls = decls->next; } ast_print(tree->right,outfile,indent+2); INDENT(indent,outfile); @@ -4503,11 +5030,14 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* just get the type */ if (tree->type == EX_VALUE) { - if (IS_LITERAL (tree->opval.val->etype)) { - fprintf(outfile,"CONSTANT (%p) value = %d, 0x%x, %g", tree, - (int) floatFromVal(tree->opval.val), - (int) floatFromVal(tree->opval.val), - floatFromVal(tree->opval.val)); + if (IS_LITERAL (tree->opval.val->etype)) { + fprintf(outfile,"CONSTANT (%p) value = ", tree); + if (SPEC_USIGN (tree->opval.val->etype)) + fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val)); + else + fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val)); + fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) floatFromVal(tree->opval.val), + floatFromVal(tree->opval.val)); } else if (tree->opval.val->sym) { /* if the undefined flag is set then give error message */ if (tree->opval.val->sym->undefined) { @@ -4538,7 +5068,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) /* depending on type of operator do */ - + switch (tree->opval.op) { /*------------------------------------------------------------------*/ /*----------------------------*/ @@ -4580,25 +5110,35 @@ void ast_print (ast * tree, FILE *outfile, int indent) /*----------------------------*/ /* ++/-- operation */ /*----------------------------*/ - case INC_OP: /* incerement operator unary so left only */ + case INC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"INC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postincrement case */ + ast_print(tree->right,outfile,indent+2); /* preincrement case */ return ; case DEC_OP: + if (tree->left) + fprintf(outfile,"post-"); + else + fprintf(outfile,"pre-"); fprintf(outfile,"DEC_OP (%p) type (",tree); printTypeChain(tree->ftype,outfile); fprintf(outfile,")\n"); - ast_print(tree->left,outfile,indent+2); + ast_print(tree->left,outfile,indent+2); /* postdecrement case */ + ast_print(tree->right,outfile,indent+2); /* predecrement case */ return ; /*------------------------------------------------------------------*/ /*----------------------------*/ /* bitwise and */ /*----------------------------*/ - case '&': + case '&': if (tree->right) { fprintf(outfile,"& (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -4634,7 +5174,7 @@ void ast_print (ast * tree, FILE *outfile, int indent) ast_print(tree->left,outfile,indent+2); ast_print(tree->right,outfile,indent+2); return ; - + /*------------------------------------------------------------------*/ /*----------------------------*/ /* division */ @@ -4764,6 +5304,12 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); return ; + case SWAP: + fprintf(outfile,"SWAP (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + return ; case GETHBIT: fprintf(outfile,"GETHBIT (%p) type (",tree); printTypeChain(tree->ftype,outfile); @@ -5090,6 +5636,9 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,"FOR LOOP BODY \n"); ast_print(tree->left,outfile,indent+2); return ; + case CRITICAL: + fprintf(outfile,"CRITICAL (%p) \n",tree); + ast_print(tree->left,outfile,indent+2); default: return ; }