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);
/*-----------------------------------------------------------------*/
/* copyAstValues - copies value portion of ast if needed */
/*-----------------------------------------------------------------*/
-void
+void
copyAstValues (ast * dest, ast * src)
{
switch (src->opval.op)
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));
/* copyAst - makes a copy of a given astession */
/*-----------------------------------------------------------------*/
ast *
-copyAst (ast * src)
+copyAst (ast * src)
{
ast *dest;
if (!tree)
return NULL;
- if (tree->type == EX_OP &&
+ if (tree->type == EX_OP &&
(tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
if (tree->left)
tree=tree->left;
- else
+ else
tree=tree->right;
}
tree->left=removeIncDecOps(tree->left);
tree->right=removeIncDecOps(tree->right);
-
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePreIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*++s += 3" -> "*++s = *++s + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePreIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->right)
+ tree=tree->right;
+ }
+
+ tree->left=removePreIncDecOps(tree->left);
+ tree->right=removePreIncDecOps(tree->right);
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePostIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*s++ += 3" -> "*s++ = *s++ + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePostIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->left)
+ tree=tree->left;
+ }
+
+ tree->left=removePostIncDecOps(tree->left);
+ tree->right=removePostIncDecOps(tree->right);
+
return tree;
}
/*-----------------------------------------------------------------*/
/* hasSEFcalls - returns TRUE if tree has a function call */
/*-----------------------------------------------------------------*/
-bool
+bool
hasSEFcalls (ast * tree)
{
if (!tree)
args = args->next = newValue ();
}
}
-
+
/* save it */
addSymChain (sym);
sym->cdef = 1;
/*-----------------------------------------------------------------*/
/* reverseParms - will reverse a parameter tree */
/*-----------------------------------------------------------------*/
-static void
+static void
reverseParms (ast * ptree)
{
ast *ttree;
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 == '+' ||
/* to the array element */
char *s = SPEC_CVAL (iexpr->etype).v_char;
int i = 0;
+ int size = getSize (iexpr->ftype);
- while (*s)
+ for (i=0;i<size;i++)
{
rast = newNode (NULLOP,
rast,
newNode ('[', sym,
newAst_VALUE (valueFromLit ((float) i))),
newAst_VALUE (valueFromLit (*s))));
- i++;
s++;
}
- rast = newNode (NULLOP,
- rast,
- newNode ('=',
- newNode ('[', sym,
- newAst_VALUE (valueFromLit ((float) i))),
- newAst_VALUE (valueFromLit (*s))));
// now WE don't need iexpr's symbol anymore
freeStringSymbol(AST_SYMBOL(iexpr));
/* if type is SPECIFIER */
if (IS_SPEC (type))
rast = createIvalType (sym, type, ilist);
-
+
if (wid)
return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)));
else
static int charLbl = 0;
symbol *sym;
set *sp;
+ int size;
// have we heard this before?
for (sp=statsg->syms; sp; sp=sp->next) {
sym=sp->item;
- if (sym->isstrlit &&
- !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) {
+ size = getSize (sym->type);
+ if (sym->isstrlit && size == getSize (val->type) &&
+ !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
// yes, this is old news. Don't publish it again.
sym->isstrlit++; // but raise the usage count
return symbolVal(sym);
return tree;
}
+
/*-------------------------------------------------------------*/
/* constExprTree - returns TRUE if this tree is a constant */
/* expression */
}
cexpr = decorateType (resolveSymbols (cexpr));
-
+
switch (cexpr->type)
{
case EX_VALUE:
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;
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");
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 */
case RRC:
case RLC:
case GETHBIT:
+ case SWAP:
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
return FALSE;
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);
/* 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)
{
newNode ('=',
newAst_VALUE (symbolVal (sym)),
end));
-
+
replLoopSym (loop->left, sym);
setAstLineno (rloop, init->lineno);
-
+
rloop = newNode (NULLOP,
newNode ('=',
newAst_VALUE (symbolVal (sym)),
newAst_VALUE (symbolVal (sym)),
newAst_VALUE (constVal ("1"))),
rloop))));
-
+
rloop->lineno=init->lineno;
return decorateType (rloop);
-
+
}
/*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type cheking */
+/* 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 checking */
/* this is done bottom up, since type have to flow upwards */
/* it also does constant folding, and paramater checking */
/*-----------------------------------------------------------------*/
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 == '=') &&
}
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;
/*------------------------------------------------------------------*/
/* 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;
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_EEPROM;
break;
case UPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
case ARRAY:
case FUNCTION:
break;
}
-
+
+ /* This breaks with extern declarations, bitfields, and perhaps other */
+ /* cases (gcse). Let's leave this optimization disabled for now and */
+ /* ponder if there's a safe way to do this. -- EEP */
+ #if 0
+ if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
+ && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
+ {
+ /* If defined struct type at addr var
+ then rewrite (&struct var)->member
+ as temp
+ and define membertype at (addr+offsetof(struct var,member)) temp
+ */
+ symbol *sym;
+ symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
+ AST_SYMBOL(tree->right));
+
+ sym = newSymbol(genSymName (0), 0);
+ sym->type = TTYPE (tree);
+ sym->etype = getSpec(sym->type);
+ sym->lineDef = tree->lineno;
+ sym->cdef = 1;
+ sym->isref = 1;
+ SPEC_STAT (sym->etype) = 1;
+ SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
+ + element->offset;
+ SPEC_ABSA(sym->etype) = 1;
+ addSym (SymbolTab, sym, sym->name, 0, 0, 0);
+ allocGlobal (sym);
+
+ AST_VALUE (tree) = symbolVal(sym);
+ TLVAL (tree) = 1;
+ TRVAL (tree) = 0;
+ tree->type = EX_VALUE;
+ tree->left = NULL;
+ tree->right = NULL;
+ }
+ #endif
+
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP:
case DEC_OP:
{
sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
- if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
+ if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
if (tree->right)
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;
}
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_REGISTER)
+ if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
{
werror (E_ILLEGAL_ADDR, "address of register variable");
goto errorTreeReturn;
werror (E_LVALUE_REQUIRED, "address of");
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_CODE)
- {
- DCL_TYPE (p) = CPOINTER;
- DCL_PTR_CONST (p) = port->mem.code_ro;
- }
+ if (!LETYPE (tree))
+ DCL_TYPE (p) = POINTER;
+ else if (SPEC_SCLS (tree->left->etype) == S_CODE)
+ DCL_TYPE (p) = CPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
DCL_TYPE (p) = FPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
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;
/*------------------------------------------------------------------*/
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 */
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),
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;
/*------------------------------------------------------------------*/
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;
}
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),
/* if unary plus */
if (!tree->right)
{
- if (!IS_INTEGRAL (LTYPE (tree)))
+ if (!IS_ARITHMETIC (LTYPE (tree)))
{
werror (E_UNARY_OP, '+');
goto errorTreeReturn;
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)) )
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 */
/*----------------------------*/
case RRC:
case RLC:
+ case SWAP:
TTYPE (tree) = LTYPE (tree);
TETYPE (tree) = LETYPE (tree);
return tree;
}
}
LRVAL (tree) = RRVAL (tree) = 1;
- if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree)))
- {
- COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree));
- }
- else
- {
- COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
- }
+ TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+ if (IS_LITERAL (TTYPE (tree)))
+ SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
return tree;
/*------------------------------------------------------------------*/
werror (E_CAST_ILLEGAL);
goto errorTreeReturn;
}
-
+
/* make sure the type is complete and sane */
checkTypeSanity(LETYPE(tree), "(cast)");
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;
}
-#endif
+
+ /* handle offsetof macro: */
+ /* #define offsetof(TYPE, MEMBER) \ */
+ /* ((unsigned) &((TYPE *)0)->MEMBER) */
+ if (IS_ADDRESS_OF_OP(tree->right)
+ && IS_AST_OP (tree->right->left)
+ && tree->right->left->opval.op == PTR_OP
+ && IS_AST_OP (tree->right->left->left)
+ && tree->right->left->left->opval.op == CAST
+ && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
+
+ symbol *element = getStructElement (
+ SPEC_STRUCT (LETYPE(tree->right->left)),
+ AST_SYMBOL(tree->right->left->right)
+ );
+
+ if (element) {
+ tree->type = EX_VALUE;
+ tree->opval.val = valCastLiteral (
+ LTYPE (tree),
+ element->offset
+ + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
+ );
+
+ TTYPE (tree) = tree->opval.val->type;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ tree->left = NULL;
+ tree->right = NULL;
+ return tree;
+ }
+ }
+
+ /* 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 (RTYPE (tree)));
+ SPEC_ABSA(sym->etype) = 1;
+ addSym (SymbolTab, sym, sym->name, 0, 0, 0);
+ allocGlobal (sym);
+
+ newTree->left = newAst_VALUE(symbolVal(sym));
+ newTree->left->lineno = tree->lineno;
+ LTYPE (newTree) = sym->type;
+ LETYPE (newTree) = sym->etype;
+ LLVAL (newTree) = 1;
+ LRVAL (newTree) = 0;
+ TLVAL (newTree) = 1;
+ return newTree;
+ }
+ if (!IS_PTR (LTYPE (tree))) {
+ tree->type = EX_VALUE;
+ tree->opval.val =
+ valCastLiteral (LTYPE (tree),
+ floatFromVal (valFromType (RTYPE (tree))));
+ TTYPE (tree) = tree->opval.val->type;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->values.literalFromCast = 1;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ return tree;
+ }
+ }
+ TTYPE (tree) = LTYPE (tree);
+ LRVAL (tree) = 1;
+
+#endif
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
IS_LITERAL (LTYPE (tree)))
{
tree->type = EX_VALUE;
- tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
+ tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+ valFromType (RTYPE (tree)),
tree->opval.op);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
/* 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;
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
werror (E_COMPARE_OP);
- fprintf (stderr, "comparring type ");
+ fprintf (stderr, "comparing type ");
printTypeChain (LTYPE (tree), stderr);
fprintf (stderr, "to type ");
printTypeChain (RTYPE (tree), stderr);
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
- werror (E_CODE_WRITE, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
if (LRVAL (tree))
{
- werror (E_LVALUE_REQUIRED, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
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))
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));
(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);
}
(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);
(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);
(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);
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 */
/*-----------------------------------------------------------------*/
addSet (&operKeyReset, name);
applyToSet (operKeyReset, resetParmKey);
- if (options.debug)
+ if (options.debug)
cdbStructBlock(1);
cleanUpLevel (LabelTab, 0);
void ast_print (ast * tree, FILE *outfile, int indent)
{
-
+
if (!tree) return ;
/* can print only decorated trees */
fprintf(outfile,"ERROR_NODE(%p)\n",tree);
}
-
+
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
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 (");
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);
/* depending on type of operator do */
-
+
switch (tree->opval.op) {
/*------------------------------------------------------------------*/
/*----------------------------*/
/*----------------------------*/
/* ++/-- 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);
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* division */
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,"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 ;
}
{
ast_print(t,stdout,0);
}
+
+
+
+/*-----------------------------------------------------------------*/
+/* astErrors : returns non-zero if errors present in tree */
+/*-----------------------------------------------------------------*/
+int astErrors(ast *t)
+{
+ int errors=0;
+
+ if (t)
+ {
+ if (t->isError)
+ errors++;
+
+ if (t->type == EX_VALUE
+ && t->opval.val->sym
+ && t->opval.val->sym->undefined)
+ errors++;
+
+ errors += astErrors(t->left);
+ errors += astErrors(t->right);
+ }
+
+ return errors;
+}