symbol *currFunc;
static ast *createIval (ast *, sym_link *, initList *, ast *);
static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
ast *optimizeGetHbit (ast *);
ast *backPatchLabels (ast *, symbol *, symbol *);
/* copyAst - makes a copy of a given astession */
/*-----------------------------------------------------------------*/
ast *
-copyAst (ast * src)
+copyAst (ast * src)
{
ast *dest;
}
+/*-----------------------------------------------------------------*/
+/* removeIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*s++ += 3" -> "*s++ = *s++ + 3" */
+/*-----------------------------------------------------------------*/
+ast *removeIncDecOps (ast * tree) {
+
+ // traverse the tree and remove inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->left)
+ tree=tree->left;
+ else
+ tree=tree->right;
+ }
+
+ tree->left=removeIncDecOps(tree->left);
+ tree->right=removeIncDecOps(tree->right);
+
+ return tree;
+}
+
/*-----------------------------------------------------------------*/
/* hasSEFcalls - returns TRUE if tree has a function call */
/*-----------------------------------------------------------------*/
if (tree == NULL)
return tree;
+#if 0
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
filename = tree->filename;
lineno = tree->lineno;
}
+#endif
/* make sure we resolve the true & false labels for ifx */
if (tree->type == EX_OP && tree->opval.op == IFX)
/*-----------------------------------------------------------------*/
/* setAstLineno - walks a ast tree & sets the line number */
/*-----------------------------------------------------------------*/
-int
-setAstLineno (ast * tree, int lineno)
+int setAstLineno (ast * tree, int lineno)
{
if (!tree)
return 0;
DCL_TYPE (sym->type) = FUNCTION;
sym->type->next = copyLinkChain (type);
sym->etype = getSpec (sym->type);
- FUNC_ISREENT(sym->type) = rent;
+ FUNC_ISREENT(sym->type) = rent ? 1 : 0;
/* if arguments required */
if (nArgs)
/* make a copy and change the regparm type to the defined parm */
actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
+ SPEC_ARGREG (actParm->etype) = SPEC_ARGREG (defParm->etype);
(*parmNumber)++;
return 0;
}
newNode ('[', sym,
newAst_VALUE (valueFromLit ((float) i))),
newAst_VALUE (valueFromLit (*s))));
+
+ // now we don't need iexpr's symbol anymore
+ {
+ symbol *sym=AST_SYMBOL(iexpr);
+ memmap *segment=SPEC_OCLS(sym->etype);
+ deleteSetItem(&segment->syms, sym);
+ }
return decorateType (resolveSymbols (rast));
}
/* if there is an initial value */
if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
{
+ initList *ilist=sym->ival;
+
+ while (ilist->type == INIT_DEEP) {
+ ilist = ilist->init.deep;
+ }
+
+ /* update lineno for error msg */
+ lineno=sym->lineDef;
+ setAstLineno (ilist->init.node, lineno);
+
if (IS_AGGREGATE (sym->type)) {
work = initAggregates (sym, sym->ival, NULL);
} else {
work = newNode ('=', newAst_VALUE (symbolVal (sym)),
list2expr (sym->ival));
}
-
+
+ // just to be sure
setAstLineno (work, sym->lineDef);
+
sym->ival = NULL;
if (init)
init = newNode (NULLOP, init, work);
return tree;
}
+/*-------------------------------------------------------------*/
+/* constExprTree - returns TRUE if this tree is a constant */
+/* expression */
+/*-------------------------------------------------------------*/
+bool constExprTree (ast *cexpr) {
+
+ if (!cexpr) {
+ return TRUE;
+ }
+
+ cexpr = decorateType (resolveSymbols (cexpr));
+
+ switch (cexpr->type)
+ {
+ case EX_VALUE:
+ if (IS_AST_LIT_VALUE(cexpr)) {
+ // this is a literal
+ return TRUE;
+ }
+ if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
+ // a function's address will never change
+ return TRUE;
+ }
+ if (IS_AST_SYM_VALUE(cexpr) &&
+ 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
+ return TRUE;
+ }
+ return FALSE;
+ case EX_LINK:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "unexpected link in expression tree\n");
+ return FALSE;
+ case EX_OP:
+ if (cexpr->opval.op==ARRAYINIT) {
+ // this is a list of literals
+ return TRUE;
+ }
+ if (cexpr->opval.op=='=') {
+ return constExprTree(cexpr->right);
+ }
+ if (cexpr->opval.op==CAST) {
+ // jwk: cast ignored, maybe we should throw a warning here
+ return constExprTree(cexpr->right);
+ }
+ if (cexpr->opval.op=='&') {
+ return TRUE;
+ }
+ if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
+ return FALSE;
+ }
+ if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/*-----------------------------------------------------------------*/
/* constExprValue - returns the value of a constant expression */
/* or NULL if it is not a constant expression */
/* if we are casting a literal value then */
if (IS_AST_OP (cexpr) &&
cexpr->opval.op == CAST &&
- IS_LITERAL (cexpr->left->ftype))
+ IS_LITERAL (cexpr->right->ftype))
return valCastLiteral (cexpr->ftype,
- floatFromVal (cexpr->left->opval.val));
+ floatFromVal (cexpr->right->opval.val));
if (IS_AST_VALUE (cexpr))
return cexpr->opval.val;
/* if we reach the end or a leaf then true */
if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
return TRUE;
-
-
+
/* if anything else is "volatile" */
if (IS_VOLATILE (TETYPE (pbody)))
return FALSE;
{
/*------------------------------------------------------------------*/
case '[':
+ // if the loopvar is used as an index
+ if (astHasSymbol(pbody->right, sym)) {
+ return FALSE;
+ }
return isConformingBody (pbody->right, sym, body);
/*------------------------------------------------------------------*/
if (astHasVolatile (pbody->left))
return FALSE;
- if (IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
+ if (IS_AST_SYM_VALUE (pbody->left)) {
+ // if the loopvar has an assignment
+ if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
+ // if the loopvar is used in another (maybe conditional) block
+ if (astHasSymbol (pbody->right, sym) &&
+ (pbody->level > body->level)) {
+ return FALSE;
+ }
+ }
if (astHasVolatile (pbody->left))
return FALSE;
/* function call */
/*----------------------------*/
case CALL:
+ /* if local & not passed as paramater then ok */
+ if (sym->level && !astHasSymbol(pbody->right,sym))
+ return TRUE;
return FALSE;
/*------------------------------------------------------------------*/
rloop = newNode (NULLOP,
createIf (newAst_VALUE (symbolVal (sym)),
newNode (GOTO,
- newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
+ newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
NULL), NULL),
newNode ('=',
newAst_VALUE (symbolVal (sym)),
end));
-
+
replLoopSym (loop->left, sym);
-
+ setAstLineno (rloop, init->lineno);
+
rloop = newNode (NULLOP,
newNode ('=',
newAst_VALUE (symbolVal (sym)),
loop->left,
newNode (NULLOP,
newNode (SUB_ASSIGN,
- newAst_VALUE (symbolVal (sym)),
- newAst_VALUE (constVal ("1"))),
+ newAst_VALUE (symbolVal (sym)),
+ newAst_VALUE (constVal ("1"))),
rloop))));
-
+
+ rloop->lineno=init->lineno;
return decorateType (rloop);
-
+
}
/*-----------------------------------------------------------------*/
tree->decorated = 1;
+#if 0
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
filename = tree->filename;
lineno = tree->lineno;
}
+#endif
/* if any child is an error | this one is an error do nothing */
if (tree->isError ||
tree->left = dtl;
if (dtr != tree->right)
tree->right = dtr;
+
+ /* special case for left shift operation : cast up right->left if type of left
+ has greater size than right */
+ if (tree->left && tree->right && tree->right->opval.op == LEFT_OP) {
+ int lsize = getSize(LTYPE(tree));
+ int rsize = getSize(RTYPE(tree));
+
+ if (lsize > rsize) {
+ tree->right->decorated = 0;
+ tree->right->left = newNode( CAST, (lsize == 2 ?
+ newAst_LINK(newIntLink()) :
+ newAst_LINK(newLongLink())),
+ tree->right->left);
+ tree->right = decorateType(tree->right);
+ }
+ }
}
/* depending on type of operator do */
/*----------------------------*/
case PTR_OP:
/* if not pointer to a structure */
- if (!IS_PTR (LTYPE (tree)))
+ if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
{
werror (E_PTR_REQD);
goto errorTreeReturn;
case UPOINTER:
case ARRAY:
case FUNCTION:
+ break;
}
return tree;
if (IS_FUNC (LTYPE (tree)))
{
- werror (E_ILLEGAL_ADDR, "address of function");
- goto errorTreeReturn;
+ // this ought to be ignored
+ return (tree->left);
}
if (IS_LITERAL(LTYPE(tree)))
LRVAL (tree) = RRVAL (tree) = 1;
/* if the left is a pointer */
- if (IS_PTR (LTYPE (tree)))
+ if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
TETYPE (tree) = getSpec (TTYPE (tree) =
LTYPE (tree));
else
tree->opval.val->type);
return tree;
}
+#if 0
+ /* a left shift must be done with at least 16bits */
+ if ((tree->opval.op==LEFT_OP) && (getSize(LTYPE(tree))<2)) {
+ // insert a cast
+ if (IS_AST_SYM_VALUE(tree->left) || IS_AST_OP(tree->left)) {
+ tree->left =
+ decorateType (newNode (CAST,
+ newAst_LINK(copyLinkChain(LTYPE(tree))),
+ tree->left));
+ SPEC_NOUN(tree->left->left->ftype)=V_INT;
+ } else {
+ // must be a literal, we can do it right away
+ SPEC_NOUN(tree->left->opval.val->type)=V_INT;
+ }
+ }
+#endif
/* if only the right side is a literal & we are
shifting more than size of the left operand then zero */
if (IS_LITERAL (RTYPE (tree)) &&
((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
(getSize (LTYPE (tree)) * 8))
{
- werror (W_SHIFT_CHANGED,
- (tree->opval.op == LEFT_OP ? "left" : "right"));
- tree->type = EX_VALUE;
- tree->left = tree->right = NULL;
- tree->opval.val = constVal ("0");
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
+ /* if left shift then cast up */
+ if (tree->opval.op==LEFT_OP) {
+ int size = getSize(LTYPE(tree));
+ tree->left =
+ decorateType (newNode (CAST,
+ (size == 1 ? newAst_LINK(newIntLink()) :
+ (size == 2 ? newAst_LINK(newLongLink()) :
+ newAst_LINK(newIntLink()))),
+ tree->left));
+ } else {
+ werror (W_SHIFT_CHANGED,
+ (tree->opval.op == LEFT_OP ? "left" : "right"));
+ tree->type = EX_VALUE;
+ tree->left = tree->right = NULL;
+ tree->opval.val = constVal ("0");
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
}
LRVAL (tree) = RRVAL (tree) = 1;
if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree)))
LRVAL (tree) = 1;
}
#else
+#if 0 // this is already checked, now this could be explicit
/* if pointer to struct then check names */
if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
- strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) {
- werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,SPEC_STRUCT(LETYPE(tree))->tag);
- }
+ 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;
return tree;
+#if 0 // assignment operators are converted by the parser
/*------------------------------------------------------------------*/
/*----------------------------*/
/* assignment operators */
tree->opval.op = '=';
return tree;
+#endif
/*------------------------------------------------------------------*/
/*----------------------------*/
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
werror (E_TYPE_MISMATCH, "assignment", " ");
- fprintf (stderr, "type --> '");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "' ");
- fprintf (stderr, "assigned to type --> '");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, "'\n");
- goto errorTreeReturn;
+ printFromToType(RTYPE(tree),LTYPE(tree));
+ //goto errorTreeReturn;
}
/* if the left side of the tree is of type void
/*-----------------------------------------------------------------*/
/* optimizeCompare - otimizes compares for bit variables */
/*-----------------------------------------------------------------*/
-ast *
+static ast *
optimizeCompare (ast * root)
{
ast *optExpr = NULL;
vright = (root->right->type == EX_VALUE ?
root->right->opval.val : NULL);
- //#define EXPERIMENTAL
-#ifdef EXPERIMENTAL
- /* if left is unsigned and right is literal */
- if (vleft && vright &&
- IS_UNSIGNED(vleft->etype) &&
- IS_LITERAL(vright->etype)) {
- double dval=floatFromVal(vright);
- int op=root->opval.op;
-
- fprintf (stderr,"op: '");
- switch (op) {
- case LE_OP: fprintf (stderr, "<= '"); break;
- case EQ_OP: fprintf (stderr, "== '"); break;
- case GE_OP: fprintf (stderr, ">= '"); break;
- default: fprintf (stderr, "%c '", op); break;
- }
- fprintf (stderr, "%f\n", dval);
-
- switch (op)
- {
- case EQ_OP:
- case LE_OP:
- case '<':
- if (dval<0 || (op=='<' && dval==0)) {
- // unsigned is never < 0
- werror (W_IF_NEVER_TRUE);
- optExpr = newAst_VALUE (constVal("0"));
- return decorateType (optExpr);
- }
- if (dval==0) {
- if (op==LE_OP) {
- // change this into a cheaper EQ_OP
- fprintf (stderr, "warning *** changed '<=' to '==' because of unsigned\n");
- root->opval.op=EQ_OP;
- return root;
- }
- }
- break;
- case GE_OP:
- case '>':
- if (dval>0 || (op==GE_OP && dval==0)) {
- // unsigned is never < 0
- werror (W_IF_ALWAYS_TRUE);
- optExpr = newAst_VALUE (constVal("1"));
- return decorateType (optExpr);
- }
- if (dval==0) {
- if (op=='>') {
- // change this into a cheaper reversed EQ_OP
- fprintf (stderr, "warning *** changed '>' to '!=' because of unsigned\n");
- root->opval.op=EQ_OP;
- }
- }
- }
- }
-#endif
-
/* if left is a BITVAR in BITSPACE */
/* and right is a LITERAL then opt- */
/* imize else do nothing */
/*----------------------------*/
case RETURN:
fprintf(outfile,"RETURN (%p) type (",tree);
- printTypeChain(tree->right->ftype,outfile);
+ if (tree->right) {
+ printTypeChain(tree->right->ftype,outfile);
+ }
fprintf(outfile,")\n");
ast_print(tree->right,outfile,indent+2);
return ;