ast *optimizeGetAbit (ast *, RESULT_TYPE);
ast *optimizeGetByte (ast *, RESULT_TYPE);
ast *optimizeGetWord (ast *, RESULT_TYPE);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+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
+int
ptt (ast * tree)
{
printTypeChain (tree->ftype, stdout);
return dest;
}
-
+#if 0
/*-----------------------------------------------------------------*/
/* removeIncDecOps: remove for side effects in *_ASSIGN's */
/* "*s++ += 3" -> "*s++ = *s++ + 3" */
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)
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);
ttree->left = ptree->left;
ptree->left = ttree;
}
-
+
/* Now reverse */
ttree = ptree->left;
ptree->left = ptree->right;
{
RESULT_TYPE resultType;
sym_link *functype;
-
+
/* if none of them exist */
if (!defParm && !*actParm)
return 0;
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 */
}
/* decorate parameter */
- resultType = defParm ? getResultTypeFromType (defParm->etype) :
+ resultType = defParm ? getResultTypeFromType (defParm->type) :
RESULT_TYPE_NONE;
*actParm = decorateType (*actParm, resultType);
if (IS_INTEGRAL (ftype)
&& (getSize (ftype) < (unsigned) INTSIZE))
{
- newType = newAst_LINK(INTTYPE);
+ newType = newAst_LINK(INTTYPE);
}
if (IS_PTR(ftype) && !IS_GENPTR(ftype))
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;
return 0;
resolveSymbols (*actParm);
-
+
/* the parameter type must be at least castable */
if (compareType (defParm->type, (*actParm)->ftype) == 0)
{
resultType = getResultTypeFromType (defParm->etype);
pTree = resolveSymbols (copyAst (*actParm));
-
+
/* now change the current one to a cast */
(*actParm)->type = EX_OP;
(*actParm)->opval.op = CAST;
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);
}
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);
}
}
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);
{
break;
}
-
+
/* no of elements given and we */
/* have generated for all of them */
- if (!--lcnt)
+ 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;
}
}
/* for each character generate an assignment */
/* to the array element */
char *s = SPEC_CVAL (iexpr->etype).v_char;
- int i = 0;
- int symsize = getSize (type);
+ unsigned int i = 0;
+ unsigned int symsize = getSize (type);
size = getSize (iexpr->ftype);
if (symsize && size>symsize)
SPEC_SCLS (sym->etype) != S_CODE)
{
symbol *newSym;
-
+
/* insert the symbol into the symbol table */
/* with level = 0 & name = rname */
newSym = copySymbol (sym);
} 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)),
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 {
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);
}
}
}
-
+
/*-----------------------------------------------------------------*/
/* stringToSymbol - creates a symbol from a literal string */
/*-----------------------------------------------------------------*/
{
*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);
cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
- switch (cexpr->type)
+ switch (cexpr->type)
{
case EX_VALUE:
if (IS_AST_LIT_VALUE(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
// 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) {
}
return FALSE;
}
-
+
/*-----------------------------------------------------------------*/
/* constExprValue - returns the value of a constant expression */
/* or NULL if it is not a constant expression */
}
/* 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))
/* 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)
{
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))
/*-----------------------------------------------------------------*/
/* astHasVolatile - returns true if ast contains any volatile */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasVolatile (ast * tree)
{
if (!tree)
/*-----------------------------------------------------------------*/
/* astHasPointer - return true if the ast contains any ptr variable */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasPointer (ast * tree)
{
if (!tree)
/*-----------------------------------------------------------------*/
/* astHasSymbol - return true if the ast has the given symbol */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasSymbol (ast * tree, symbol * sym)
{
if (!tree || IS_AST_LINK (tree))
/*-----------------------------------------------------------------*/
/* 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);
}
/* 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)
{
/* 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 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;
/* 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)
{
/*-----------------------------------------------------------------*/
/* replLoopSym - replace the loop sym by loop sym -1 */
/*-----------------------------------------------------------------*/
-static void
+static void
replLoopSym (ast * body, symbol * sym)
{
/* reached end */
if (IS_BITFIELD (type))
{
int blen = SPEC_BLEN (type);
-
+
if (blen <= 1)
return RESULT_TYPE_BIT;
if (blen <= 8)
{
sym_link *newLink;
bool upCasted = FALSE;
-
+
switch (resultType)
{
case RESULT_TYPE_NONE:
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:
}
}
+/*------------------------------------------------------------------*/
+/* 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. */
/*--------------------------------------------------------------------*/
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;
}
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 '?':
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:
+ default:
dtr = decorateType (tree->right, resultTypeProp);
break;
}
RRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
+ 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;
+ 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;
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 */
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->right = NULL;
}
#endif
-
+
return tree;
/*------------------------------------------------------------------*/
}
LRVAL (tree) = RRVAL (tree) = 1;
-
+
TTYPE (tree) = computeType (LTYPE (tree),
RTYPE (tree),
resultType,
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);
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;
resultType,
tree->opval.op));
}
-
+
return tree;
/*------------------------------------------------------------------*/
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;
}
tree->right = litParent->left;
litParent->left = tTree;
litTree->opval.op = '+';
-
+
tree->decorated = 0;
decorateType (tree, resultType);
}
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)))
{
/* 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)))
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 */
{
if (IS_ADDRESS_OF_OP(tree->right)
&& 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);
}
addr |= gptype << (8*(GPTRSIZE - 1));
}
-
+
tree->type = EX_VALUE;
tree->opval.val =
valCastLiteral (LTYPE (tree), addr);
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)
+ werror (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)) &&
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)) &&
}
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;
/*------------------------------------------------------------------*/
/* function call */
/*----------------------------*/
case CALL:
-
+
/* undo any explicit pointer derefernce; PCALL will handle it instead */
if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
{
if (!tree->right ||
!tree->right->decorated)
{
- sym_link *functype;
+ sym_link *functype;
parmNumber = 1;
if (IS_FUNCPTR (LTYPE (tree)))
- functype = LTYPE (tree)->next;
+ {
+ functype = LTYPE (tree)->next;
+ processFuncPtrArgs (functype);
+ }
else
functype = LTYPE (tree);
{
goto errorTreeReturn;
}
-
- if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
!IFFUNC_ISBUILTIN(functype))
{
reverseParms (tree->right);
/*----------------------------*/
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
/*-----------------------------------------------------------------*/
/* 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;
/* 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))
{
ex = newNode (BLOCK, NULL, body);
ex->values.sym = decl;
-
+
ex->level++;
ex->lineno = 0;
return ex;
}
/* create the case label */
- SNPRINTF(caseLbl, sizeof(caseLbl),
+ SNPRINTF(caseLbl, sizeof(caseLbl),
"_case_%d_%d",
swStat->values.switchVals.swNum,
(int) floatFromVal (caseVal->opval.val));
if (!expr && (resultType == RESULT_TYPE_BIT))
{
expr = tree->left;
- if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1)
+ if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
expr = NULL;
}
if (!expr)
}
if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
return tree;
-
+
/* make sure the port supports GETBYTE */
if (port->hasExtBitOp
&& !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
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 (!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))))
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) &&
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;
/*-----------------------------------------------------------------*/
/* addSymToBlock : adds the symbol to the first block we find */
/*-----------------------------------------------------------------*/
-void
+void
addSymToBlock (symbol * sym, ast * tree)
{
/* reached end of tree or a leaf */
/*-----------------------------------------------------------------*/
/* processRegParms - do processing for register parameters */
/*-----------------------------------------------------------------*/
-static void
+static void
processRegParms (value * args, ast * body)
{
while (args)
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);
} else {
fprintf(outfile,"SYMBOL ");
}
- fprintf(outfile,"(%s=%p)",
- tree->opval.val->sym->name,tree);
+ fprintf(outfile,"(%s=%p @ %p)",
+ tree->opval.val->sym->name, tree, tree->opval.val->sym);
}
if (tree->ftype) {
fprintf(outfile," type (");
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");
fprintf(outfile,")\n");
ast_print(tree->right,outfile,indent+2);
return ;
-
+
case AND_OP:
fprintf(outfile,"ANDAND (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* comparison operators */
fprintf(outfile,")\n");
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
- return;
+ return;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* comma operator */
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 += astErrors(t->left);
errors += astErrors(t->right);
}
-
+
return errors;
}