what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
+#define DEBUG_CF(x) /* puts(x); */
+
#include "common.h"
int currLineno = 0;
set *operKeyReset = NULL;
ast *staticAutos = NULL;
int labelKey = 1;
+static struct {
+ int count; /* number of inline functions inserted */
+ symbol * retsym; /* variable for inlined function return value */
+ symbol * retlab; /* label ending inlined function (virtual return) */
+} inlineState;
#define LRVAL(x) x->left->rvalue
#define RRVAL(x) x->right->rvalue
int noLineno = 0;
int noAlloc = 0;
symbol *currFunc=NULL;
-static ast *createIval (ast *, sym_link *, initList *, ast *);
-static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
+static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
ast *optimizeSWAP (ast *);
-ast *optimizeGetHbit (ast *);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+ast *optimizeGetHbit (ast *, RESULT_TYPE);
+ast *optimizeGetAbit (ast *, RESULT_TYPE);
+ast *optimizeGetByte (ast *, RESULT_TYPE);
+ast *optimizeGetWord (ast *, RESULT_TYPE);
+static ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
int inInitMode = 0;
memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
-FILE *codeOutFile;
-int
+struct dbuf_s *codeOutBuf;
+int
ptt (ast * tree)
{
printTypeChain (tree->ftype, stdout);
newAst_ (unsigned type)
{
ast *ex;
- static int oldLineno = 0;
ex = Safe_alloc ( sizeof (ast));
ex->type = type;
- ex->lineno = (noLineno ? oldLineno : mylineno);
- ex->filename = currFname;
+ ex->lineno = (noLineno ? 0 : lexLineno);
+ ex->filename = lexFilename;
ex->level = NestLevel;
ex->block = currBlockno;
ex->initMode = inInitMode;
{
/* then depending on the expression value */
if (floatFromVal (condAst->opval.val))
- ifxNode = newNode (GOTO,
- newAst_VALUE (symbolVal (trueLabel)),
- NULL);
+ ifxNode = newNode (GOTO,
+ newAst_VALUE (symbolVal (trueLabel)),
+ NULL);
else
- ifxNode = newNode (GOTO,
- newAst_VALUE (symbolVal (falseLabel)),
- NULL);
+ ifxNode = newNode (GOTO,
+ newAst_VALUE (symbolVal (falseLabel)),
+ NULL);
}
else
{
}
/*-----------------------------------------------------------------*/
-/* copyAstValues - copies value portion of ast if needed */
+/* copyAstValues - copies value portion of ast if needed */
/*-----------------------------------------------------------------*/
void
copyAstValues (ast * dest, ast * src)
case SWITCH:
dest->values.switchVals.swVals =
- copyValue (src->values.switchVals.swVals);
+ copyValue (src->values.switchVals.swVals);
dest->values.switchVals.swDefault =
- src->values.switchVals.swDefault;
+ src->values.switchVals.swDefault;
dest->values.switchVals.swNum =
- src->values.switchVals.swNum;
+ src->values.switchVals.swNum;
break;
case INLINEASM:
break;
case ARRAYINIT:
- dest->values.constlist = copyLiteralList(src->values.constlist);
- break;
+ dest->values.constlist = copyLiteralList(src->values.constlist);
+ break;
case FOR:
AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
dest = Safe_alloc ( sizeof (ast));
dest->type = src->type;
+ dest->filename = src->filename;
dest->lineno = src->lineno;
dest->level = src->level;
dest->funcName = src->funcName;
+ dest->reversed = src->reversed;
if (src->ftype)
dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
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 if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
+ /* illegal pre/post-increment/decrement */
+ werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
+ } 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)
return TRUE;
return (hasSEFcalls (tree->left) |
- hasSEFcalls (tree->right));
+ hasSEFcalls (tree->right));
}
/*-----------------------------------------------------------------*/
{
case EX_OP:
if (t1->opval.op != t2->opval.op)
- return 0;
+ return 0;
return (isAstEqual (t1->left, t2->left) &&
- isAstEqual (t1->right, t2->right));
+ isAstEqual (t1->right, t2->right));
break;
case EX_VALUE:
if (t1->opval.val->sym)
- {
- if (!t2->opval.val->sym)
- return 0;
- else
- return isSymbolEqual (t1->opval.val->sym,
- t2->opval.val->sym);
- }
+ {
+ if (!t2->opval.val->sym)
+ return 0;
+ else
+ return isSymbolEqual (t1->opval.val->sym,
+ t2->opval.val->sym);
+ }
else
- {
- if (t2->opval.val->sym)
- return 0;
- else
- return (floatFromVal (t1->opval.val) ==
- floatFromVal (t2->opval.val));
- }
+ {
+ if (t2->opval.val->sym)
+ return 0;
+ else
+ return (floatFromVal (t1->opval.val) ==
+ floatFromVal (t2->opval.val));
+ }
break;
/* only compare these two types */
symbol *csym;
if (tree->trueLabel)
- {
- if ((csym = findSym (LabelTab, tree->trueLabel,
- tree->trueLabel->name)))
- tree->trueLabel = csym;
- else
- werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
- tree->trueLabel->name);
- }
+ {
+ if ((csym = findSym (LabelTab, tree->trueLabel,
+ tree->trueLabel->name)))
+ tree->trueLabel = csym;
+ else
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->trueLabel->name);
+ }
if (tree->falseLabel)
- {
- if ((csym = findSym (LabelTab,
- tree->falseLabel,
- tree->falseLabel->name)))
- tree->falseLabel = csym;
- else
- werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
- tree->falseLabel->name);
- }
-
+ {
+ if ((csym = findSym (LabelTab,
+ tree->falseLabel,
+ tree->falseLabel->name)))
+ tree->falseLabel = csym;
+ else
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->falseLabel->name);
+ }
}
/* if this is a label resolve it from the labelTab */
tree->opval.val->sym &&
tree->opval.val->sym->islbl)
{
-
symbol *csym = findSym (LabelTab, tree->opval.val->sym,
- tree->opval.val->sym->name);
+ tree->opval.val->sym->name);
if (!csym)
- werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
- tree->opval.val->sym->name);
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->opval.val->sym->name);
else
- tree->opval.val->sym = csym;
+ tree->opval.val->sym = csym;
goto resolveChildren;
}
tree->opval.val->sym &&
!tree->opval.val->sym->implicit)
{
-
symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
- /* if found in the symbol table & they r not the same */
+ /* if found in the symbol table & they are not the same */
if (csym && tree->opval.val->sym != csym)
- {
- tree->opval.val->sym = csym;
- tree->opval.val->type = csym->type;
- tree->opval.val->etype = csym->etype;
- }
+ {
+ tree->opval.val->sym = csym;
+ tree->opval.val->type = csym->type;
+ tree->opval.val->etype = csym->etype;
+ }
/* if not found in the symbol table */
- /* mark it as undefined assume it is */
- /* an integer in data space */
+ /* mark it as undefined & assume it */
+ /* is an integer in data space */
if (!csym && !tree->opval.val->sym->implicit)
- {
-
- /* if this is a function name then */
- /* mark it as returning an int */
- if (tree->funcName)
- {
- tree->opval.val->sym->type = newLink (DECLARATOR);
- DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
- tree->opval.val->sym->type->next =
- tree->opval.val->sym->etype = newIntLink ();
- tree->opval.val->etype = tree->opval.val->etype;
- tree->opval.val->type = tree->opval.val->sym->type;
- werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
- tree->opval.val->sym->name);
- //tree->opval.val->sym->undefined = 1;
- allocVariables (tree->opval.val->sym);
- }
- else
- {
- tree->opval.val->sym->undefined = 1;
- tree->opval.val->type =
- tree->opval.val->etype = newIntLink ();
- tree->opval.val->sym->type =
- tree->opval.val->sym->etype = newIntLink ();
- }
- }
+ {
+ /* if this is a function name then */
+ /* mark it as returning an int */
+ if (tree->funcName)
+ {
+ tree->opval.val->sym->type = newLink (DECLARATOR);
+ DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
+ tree->opval.val->sym->type->next =
+ tree->opval.val->sym->etype = newIntLink ();
+ tree->opval.val->etype = tree->opval.val->etype;
+ tree->opval.val->type = tree->opval.val->sym->type;
+ werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
+ tree->opval.val->sym->name);
+ //tree->opval.val->sym->undefined = 1;
+ allocVariables (tree->opval.val->sym);
+ }
+ else
+ {
+ tree->opval.val->sym->undefined = 1;
+ tree->opval.val->type =
+ tree->opval.val->etype = newIntLink ();
+ tree->opval.val->sym->type =
+ tree->opval.val->sym->etype = newIntLink ();
+ }
+ }
}
resolveChildren:
return tree;
}
-/*-----------------------------------------------------------------*/
-/* setAstLineno - walks a ast tree & sets the line number */
-/*-----------------------------------------------------------------*/
-int setAstLineno (ast * tree, int lineno)
+/*------------------------------------------------------------------------*/
+/* setAstFileLine - walks a ast tree & sets the file name and line number */
+/*------------------------------------------------------------------------*/
+int setAstFileLine (ast * tree, char *filename, int lineno)
{
if (!tree)
return 0;
+ tree->filename = filename;
tree->lineno = lineno;
- setAstLineno (tree->left, lineno);
- setAstLineno (tree->right, lineno);
+ setAstFileLine (tree->left, filename, lineno);
+ setAstFileLine (tree->right, filename, lineno);
return 0;
}
/*-----------------------------------------------------------------*/
symbol *
funcOfType (char *name, sym_link * type, sym_link * argType,
- int nArgs, int rent)
+ int nArgs, int rent)
{
symbol *sym;
/* create the symbol */
args = FUNC_ARGS(sym->type) = newValue ();
while (nArgs--)
- {
- args->type = copyLinkChain (argType);
- args->etype = getSpec (args->type);
- SPEC_EXTR(args->etype)=1;
- if (!nArgs)
- break;
- args = args->next = newValue ();
- }
+ {
+ args->type = copyLinkChain (argType);
+ args->etype = getSpec (args->type);
+ SPEC_EXTR(args->etype)=1;
+ if (!nArgs)
+ break;
+ args = args->next = newValue ();
+ }
}
/* save it */
- addSymChain (sym);
+ addSymChain (&sym);
sym->cdef = 1;
allocVariables (sym);
return sym;
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);
- SPEC_EXTR(args->etype)=1;
- if ((i + 1) == nArgs) break;
- args = args->next = newValue ();
- }
+ value *args;
+ args = FUNC_ARGS(sym->type) = newValue ();
+
+ for ( i = 0 ; i < nArgs ; i++ ) {
+ args->type = typeFromStr(atypes[i]);
+ args->etype = getSpec (args->type);
+ SPEC_EXTR(args->etype)=1;
+ if ((i + 1) == nArgs) break;
+ args = args->next = newValue ();
+ }
}
/* save it */
- addSymChain (sym);
+ addSymChain (&sym);
sym->cdef = 1;
allocVariables (sym);
return sym;
return;
/* top down if we find a nonParm tree then quit */
- if (ptree->type == EX_OP && ptree->opval.op == PARAM)
+ if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
{
+ /* The various functions expect the parameter tree to be right heavy. */
+ /* Rotate the tree to be left heavy so that after reversal it is */
+ /* right heavy again. */
+ while ((ttree = ptree->right) && ttree->type == EX_OP &&
+ ttree->opval.op == PARAM)
+ {
+ ptree->right = ttree->right;
+ ttree->right = ttree->left;
+ ttree->left = ptree->left;
+ ptree->left = ttree;
+ }
+
+ /* Now reverse */
ttree = ptree->left;
ptree->left = ptree->right;
ptree->right = ttree;
+ ptree->reversed = 1;
reverseParms (ptree->left);
reverseParms (ptree->right);
}
/* processParms - makes sure the parameters are okay and do some */
/* processing with them */
/*-----------------------------------------------------------------*/
-int
-processParms (ast * func,
- value *defParm,
- ast * actParm,
- int *parmNumber, // unused, although updated
- bool rightmost)
+static int
+processParms (ast *func,
+ value *defParm,
+ ast **actParm,
+ int *parmNumber, /* unused, although updated */
+ bool rightmost)
{
+ RESULT_TYPE resultType;
+ sym_link *functype;
+
/* if none of them exist */
- if (!defParm && !actParm)
+ if (!defParm && !*actParm)
return 0;
- if (defParm) {
- if (getenv("DEBUG_SANITY")) {
- fprintf (stderr, "processParms: %s ", defParm->name);
+ if (defParm)
+ {
+ if (getenv("DEBUG_SANITY"))
+ {
+ fprintf (stderr, "processParms: %s ", defParm->name);
+ }
+ /* make sure the type is complete and sane */
+ checkTypeSanity(defParm->etype, defParm->name);
}
- /* make sure the type is complete and sane */
- checkTypeSanity(defParm->etype, defParm->name);
- }
- /* if the function is being called via a pointer & */
- /* it has not been defined a reentrant then we cannot */
- /* have parameters */
- if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
+ if (IS_CODEPTR (func->ftype))
+ functype = func->ftype->next;
+ else
+ functype = func->ftype;
+
+ /* if the function is being called via a pointer & */
+ /* it has not been defined reentrant then we cannot */
+ /* have parameters */
+ /* PIC16 port can... */
+ if (!TARGET_IS_PIC16)
{
- werror (W_NONRENT_ARGS);
- return 1;
+ if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+ {
+ werror (E_NONRENT_ARGS);
+ fatalError++;
+ return 1;
+ }
}
/* if defined parameters ended but actual parameters */
/* exist and this is not defined as a variable arg */
- if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
+ if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
{
- //if (func->type==EX_VALUE && func->opval.val->sym->undefined)
- // return 1; /* Already gave them an undefined function error */
werror (E_TOO_MANY_PARMS);
return 1;
}
/* if defined parameters present but no actual parameters */
- if (defParm && !actParm)
+ if (defParm && !*actParm)
{
werror (E_TOO_FEW_PARMS);
return 1;
}
- if (IS_VOID(actParm->ftype)) {
- werror (E_VOID_VALUE_USED);
- return 1;
- }
+ /* if this is a PARAM node then match left & right */
+ if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
+ {
+ (*actParm)->decorated = 1;
+ return (processParms (func, defParm,
+ &(*actParm)->left, parmNumber, FALSE) ||
+ processParms (func, defParm ? defParm->next : NULL,
+ &(*actParm)->right, parmNumber, rightmost));
+ }
+ else if (defParm) /* not vararg */
+ {
+ /* If we have found a value node by following only right-hand links,
+ * then we know that there are no more values after us.
+ *
+ * Therefore, if there are more defined parameters, the caller didn't
+ * supply enough.
+ */
+ if (rightmost && defParm->next)
+ {
+ werror (E_TOO_FEW_PARMS);
+ return 1;
+ }
+ }
+
+ /* decorate parameter */
+ resultType = defParm ? getResultTypeFromType (defParm->type) :
+ RESULT_TYPE_NONE;
+ *actParm = decorateType (*actParm, resultType);
+
+ if (IS_VOID((*actParm)->ftype))
+ {
+ werror (E_VOID_VALUE_USED);
+ return 1;
+ }
/* If this is a varargs function... */
- if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
+ if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
{
ast *newType = NULL;
sym_link *ftype;
- if (IS_CAST_OP (actParm)
- || (IS_AST_LIT_VALUE (actParm) && actParm->values.literalFromCast))
- {
- /* Parameter was explicitly typecast; don't touch it. */
- return 0;
- }
+ /* don't perform integer promotion of explicitly typecasted variable arguments
+ * if sdcc extensions are enabled */
+ if (options.std_sdcc &&
+ (IS_CAST_OP (*actParm) ||
+ (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
+ (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
+ {
+ /* Parameter was explicitly typecast; don't touch it. */
+ return 0;
+ }
+
+ ftype = (*actParm)->ftype;
- ftype = actParm->ftype;
-
- /* If it's a small integer, upcast to int. */
+ /* If it's a char, upcast to int. */
if (IS_INTEGRAL (ftype)
- && (getSize (ftype) < (unsigned) INTSIZE))
- {
- if (IS_AST_OP(actParm) &&
- (actParm->opval.op == LEFT_OP ||
- actParm->opval.op == '*' ||
- actParm->opval.op == '+' ||
- actParm->opval.op == '-') &&
- actParm->right) {
- // we should cast an operand instead of the result
- actParm->decorated = 0;
- actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
- actParm->left);
- actParm = decorateType(actParm, RESULT_CHECK);
- } else {
- newType = newAst_LINK(INTTYPE);
- }
- }
+ && (getSize (ftype) < (unsigned) INTSIZE))
+ {
+ newType = newAst_LINK(INTTYPE);
+ }
if (IS_PTR(ftype) && !IS_GENPTR(ftype))
- {
- newType = newAst_LINK (copyLinkChain(ftype));
- DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
- }
+ {
+ newType = newAst_LINK (copyLinkChain(ftype));
+ DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+ }
if (IS_AGGREGATE (ftype))
- {
- newType = newAst_LINK (copyLinkChain (ftype));
- DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
- }
+ {
+ newType = newAst_LINK (copyLinkChain (ftype));
+ DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+ }
+
if (newType)
- {
- /* cast required; change this op to a cast. */
- ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK);
-
- actParm->type = EX_OP;
- actParm->opval.op = CAST;
- actParm->left = newType;
- actParm->right = parmCopy;
- decorateType (actParm, RESULT_CHECK);
- }
- else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
- {
- return (processParms (func, NULL, actParm->left, parmNumber, FALSE) ||
- processParms (func, NULL, actParm->right, parmNumber, rightmost));
- }
+ {
+ /* cast required; change this op to a cast. */
+ (*actParm)->decorated = 0;
+ *actParm = newNode (CAST, newType, *actParm);
+ (*actParm)->filename = (*actParm)->right->filename;
+ (*actParm)->lineno = (*actParm)->right->lineno;
+
+ decorateType (*actParm, RESULT_TYPE_NONE);
+ }
return 0;
- }
+ } /* vararg */
/* if defined parameters ended but actual has not & */
/* reentrant */
- if (!defParm && actParm &&
- (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
+ if (!defParm && *actParm &&
+ (options.stackAuto || IFFUNC_ISREENT (functype)))
return 0;
- resolveSymbols (actParm);
- /* if this is a PARAM node then match left & right */
- if (actParm->type == EX_OP && actParm->opval.op == PARAM)
- {
- return (processParms (func, defParm, actParm->left, parmNumber, FALSE) ||
- processParms (func, defParm->next, actParm->right, parmNumber, rightmost));
- }
- else
- {
- /* If we have found a value node by following only right-hand links,
- * then we know that there are no more values after us.
- *
- * Therefore, if there are more defined parameters, the caller didn't
- * supply enough.
- */
- if (rightmost && defParm->next)
- {
- werror (E_TOO_FEW_PARMS);
- return 1;
- }
- }
+ resolveSymbols (*actParm);
/* the parameter type must be at least castable */
- if (compareType (defParm->type, actParm->ftype) == 0) {
- werror (E_INCOMPAT_TYPES);
- printFromToType (actParm->ftype, defParm->type);
- return 1;
- }
+ if (compareType (defParm->type, (*actParm)->ftype) == 0)
+ {
+ werror (E_INCOMPAT_TYPES);
+ printFromToType ((*actParm)->ftype, defParm->type);
+ return 1;
+ }
/* if the parameter is castable then add the cast */
- if (compareType (defParm->type, actParm->ftype) < 0)
+ if (compareType (defParm->type, (*actParm)->ftype) < 0)
{
- ast *pTree = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK);
+ ast *pTree;
+
+ resultType = getResultTypeFromType (defParm->etype);
+ pTree = resolveSymbols (copyAst (*actParm));
/* now change the current one to a cast */
- actParm->type = EX_OP;
- actParm->opval.op = CAST;
- actParm->left = newAst_LINK (defParm->type);
- actParm->right = pTree;
- actParm->etype = defParm->etype;
- actParm->ftype = defParm->type;
- actParm->decorated=0; /* force typechecking */
- decorateType (actParm, RESULT_CHECK);
+ (*actParm)->type = EX_OP;
+ (*actParm)->opval.op = CAST;
+ (*actParm)->left = newAst_LINK (defParm->type);
+ (*actParm)->right = pTree;
+ (*actParm)->decorated = 0; /* force typechecking */
+ decorateType (*actParm, IS_GENPTR (defParm->type) ? RESULT_TYPE_GPTR : resultType);
}
/* 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);
+ (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
+ SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
+ SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
+
+ /* if the function is being called via a pointer & */
+ /* this parameter is not passed in registers */
+ /* then the function must be defined reentrant */
+ if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
+ !IFFUNC_ISREENT (functype) && !options.stackAuto)
+ {
+ werror (E_NONRENT_ARGS);
+ fatalError++;
+ return 1;
+ }
+
(*parmNumber)++;
return 0;
}
+
/*-----------------------------------------------------------------*/
/* createIvalType - generates ival for basic types */
/*-----------------------------------------------------------------*/
ast *iExpr;
/* if initList is deep */
- if (ilist->type == INIT_DEEP)
+ if (ilist && ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
- return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
+ if (ilist)
+ iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+ else
+ iExpr = newAst_VALUE (valueFromLit (0));
+ return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
/* createIvalStruct - generates initial value for structures */
/*-----------------------------------------------------------------*/
static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist)
+createIvalStruct (ast *sym, sym_link *type, initList *ilist, ast *rootValue)
{
ast *rast = NULL;
ast *lAst;
symbol *sflds;
initList *iloop;
+ sym_link * etype = getSpec (type);
- sflds = SPEC_STRUCT (type)->fields;
- if (ilist->type != INIT_DEEP)
+ if (ilist && ilist->type != INIT_DEEP)
{
werror (E_INIT_STRUCT, "");
return NULL;
}
- iloop = ilist->init.deep;
+ iloop = ilist ? ilist->init.deep : NULL;
- for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
+ for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
{
/* if we have come to end */
- if (!iloop)
- break;
- sflds->implicit = 1;
- lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
- lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
- rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
+ if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+ break;
+
+ if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
+ {
+ sflds->implicit = 1;
+ lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
+ lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+ rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast, rootValue)), RESULT_TYPE_NONE);
+ iloop = iloop ? iloop->next : NULL;
+ }
}
- if (iloop) {
- werrorfl (filename, sym->opval.val->sym->lineDef,
- W_EXCESS_INITIALIZERS, "struct",
- sym->opval.val->sym->name);
- }
+ if (iloop)
+ {
+ if (IS_AST_VALUE (sym))
+ werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+ W_EXCESS_INITIALIZERS, "struct",
+ sym->opval.val->sym->name);
+ else
+ werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
+ }
return rast;
}
-
/*-----------------------------------------------------------------*/
/* createIvalArray - generates code for array initialization */
/*-----------------------------------------------------------------*/
static ast *
-createIvalArray (ast * sym, sym_link * type, initList * ilist)
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
{
ast *rast = NULL;
initList *iloop;
int lcnt = 0, size = 0;
literalList *literalL;
+ sym_link * etype = getSpec (type);
/* take care of the special case */
/* array of characters can be init */
/* by a string */
if (IS_CHAR (type->next))
if ((rast = createIvalCharPtr (sym,
- type,
- decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
+ type,
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+ rootValue)))
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
- /* not the special case */
- if (ilist->type != INIT_DEEP)
+ /* not the special case */
+ if (ilist && ilist->type != INIT_DEEP)
{
- werror (E_INIT_STRUCT, "");
- return NULL;
+ werror (E_INIT_STRUCT, "");
+ return NULL;
}
- iloop = ilist->init.deep;
- lcnt = DCL_ELEM (type);
+ iloop = ilist ? ilist->init.deep : NULL;
+ lcnt = DCL_ELEM (type);
- if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+ if (!iloop &&
+ (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
{
- ast *aSym;
-
- aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
-
- 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;
-
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
- }
+ return NULL;
}
- else
+
+ if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
+ {
+ 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.
+ werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+ W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
+ }
+ }
+ else
{
- for (;;)
- {
- ast *aSym;
-
- aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
- aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
- rast = createIval (aSym, type->next, iloop, rast);
- iloop = (iloop ? iloop->next : NULL);
- if (!iloop)
- {
- break;
- }
-
- /* no of elements given and we */
- /* have generated for all of them */
- if (!--lcnt)
- {
- // there has to be a better way
- char *name=sym->opval.val->sym->name;
- int lineno=sym->opval.val->sym->lineDef;
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-
- break;
- }
- }
+ for (;;)
+ {
+ ast *aSym;
+
+ if (!iloop &&
+ (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+ {
+ break;
+ }
+
+ aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
+ aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+ rast = createIval (aSym, type->next, iloop, rast, rootValue);
+ lcnt--;
+ iloop = (iloop ? iloop->next : NULL);
+
+ /* no of elements given and we */
+ /* have generated for all of them */
+ if (!lcnt && iloop)
+ {
+ // is this a better way? at least it won't crash
+ char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+ werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
+
+ break;
+ }
+ }
}
- /* if we have not been given a size */
- if (!DCL_ELEM (type))
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
{
- DCL_ELEM (type) = size;
+ /* check, if it's a flexible array */
+ if (IS_STRUCT (AST_VALUE (rootValue)->type))
+ AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
+ else
+ DCL_ELEM (type) = size;
}
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/* createIvalCharPtr - generates initial values for char pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
+createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
{
ast *rast = NULL;
+ unsigned size = 0;
/* if this is a pointer & right is a literal array then */
/* just assignment will do */
if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
- SPEC_SCLS (iexpr->etype) == S_CODE)
- && IS_ARRAY (iexpr->ftype)))
+ SPEC_SCLS (iexpr->etype) == S_CODE)
+ && IS_ARRAY (iexpr->ftype)))
return newNode ('=', sym, iexpr);
- /* left side is an array so we have to assign each */
- /* element */
+ /* left side is an array so we have to assign each element */
+ if (!iexpr)
+ {
+ /* for each character generate an assignment */
+ /* to the array element */
+ unsigned int i = 0;
+ unsigned int symsize = getSize (type);
+
+ if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
+ return NULL;
+
+ for (i = 0; i < symsize; ++i)
+ {
+ rast = newNode (NULLOP,
+ rast,
+ newNode ('=',
+ newNode ('[', sym,
+ newAst_VALUE (valueFromLit ((float) i))),
+ newAst_VALUE (valueFromLit (0))));
+ }
+
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+ }
+
if ((IS_LITERAL (iexpr->etype) ||
SPEC_SCLS (iexpr->etype) == S_CODE)
&& IS_ARRAY (iexpr->ftype))
/* for each character generate an assignment */
/* to the array element */
char *s = SPEC_CVAL (iexpr->etype).v_char;
- int i = 0;
- int size = getSize (iexpr->ftype);
- int symsize = getSize (type);
-
- if (size>symsize)
- {
- if (size>(symsize+1))
- werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
- "string", sym->opval.val->sym->name);
- size = symsize;
- }
-
- for (i=0;i<size;i++)
- {
- rast = newNode (NULLOP,
- rast,
- newNode ('=',
- newNode ('[', sym,
- newAst_VALUE (valueFromLit ((float) i))),
- newAst_VALUE (valueFromLit (*s))));
- s++;
- }
+ unsigned int i = 0;
+ unsigned int symsize = getSize (type);
+
+ size = getSize (iexpr->ftype);
+ if (symsize && size > symsize)
+ {
+ if (size > symsize)
+ {
+ char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+ werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+ "string", name);
+ }
+ size = symsize;
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ 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));
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
+ {
+ /* check, if it's a flexible array */
+ if (IS_STRUCT (AST_VALUE (rootVal)->type))
+ AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+ else
+ DCL_ELEM (type) = size;
+ }
+
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
return NULL;
/* createIvalPtr - generates initial value for pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalPtr (ast * sym, sym_link * type, initList * ilist)
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
{
ast *rast;
ast *iexpr;
/* if deep then */
- if (ilist->type == INIT_DEEP)
+ if (ilist && ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
+ iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
/* if character pointer */
if (IS_CHAR (type->next))
- if ((rast = createIvalCharPtr (sym, type, iexpr)))
+ if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
return rast;
return newNode ('=', sym, iexpr);
/* createIval - generates code for initial value */
/*-----------------------------------------------------------------*/
static ast *
-createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
{
ast *rast = NULL;
- if (!ilist)
+ if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
return NULL;
/* if structure then */
if (IS_STRUCT (type))
- rast = createIvalStruct (sym, type, ilist);
+ rast = createIvalStruct (sym, type, ilist, rootValue);
else
/* if this is a pointer */
if (IS_PTR (type))
- rast = createIvalPtr (sym, type, ilist);
+ rast = createIvalPtr (sym, type, ilist, rootValue);
else
/* if this is an array */
if (IS_ARRAY (type))
- rast = createIvalArray (sym, type, ilist);
+ rast = createIvalArray (sym, type, ilist, rootValue);
else
/* if type is SPECIFIER */
if (IS_SPEC (type))
rast = createIvalType (sym, type, ilist);
if (wid)
- return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
+ return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
else
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
/* initAggregates - initialises aggregate variables with initv */
/*-----------------------------------------------------------------*/
-ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
- return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
+ast * initAggregates (symbol * sym, initList * ival, ast * wid)
+{
+ ast *newAst = newAst_VALUE (symbolVal (sym));
+ return createIval (newAst, sym->type, ival, wid, newAst);
}
/*-----------------------------------------------------------------*/
/* gatherAutoInit - creates assignment expressions for initial */
-/* values */
+/* values */
/*-----------------------------------------------------------------*/
static ast *
gatherAutoInit (symbol * autoChain)
inInitMode = 1;
for (sym = autoChain; sym; sym = sym->next)
{
-
/* resolve the symbols in the ival */
if (sym->ival)
- resolveIvalSym (sym->ival);
+ resolveIvalSym (sym->ival, sym->type);
+
+#if 1
+ /* if we are PIC16 port,
+ * and this is a static,
+ * and have initial value,
+ * and not S_CODE, don't emit in gs segment,
+ * but allow glue.c:pic16emitRegularMap to put symbol
+ * in idata section */
+ if(TARGET_IS_PIC16 &&
+ IS_STATIC (sym->etype) && sym->ival
+ && SPEC_SCLS(sym->etype) != S_CODE) {
+ SPEC_SCLS (sym->etype) = S_DATA;
+ continue;
+ }
+#endif
/* if this is a static variable & has an */
/* initial value the code needs to be lifted */
/* here to the main portion since they can be */
/* initialised only once at the start */
if (IS_STATIC (sym->etype) && sym->ival &&
- SPEC_SCLS (sym->etype) != S_CODE)
- {
- symbol *newSym;
-
- /* insert the symbol into the symbol table */
- /* with level = 0 & name = rname */
- newSym = copySymbol (sym);
- addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
-
- /* now lift the code to main */
- if (IS_AGGREGATE (sym->type)) {
- work = initAggregates (sym, sym->ival, NULL);
- } else {
- if (getNelements(sym->type, sym->ival)>1) {
- werrorfl (filename, sym->lineDef,
- W_EXCESS_INITIALIZERS, "scalar",
- sym->name);
- }
- work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
- list2expr (sym->ival));
- }
-
- setAstLineno (work, sym->lineDef);
-
- sym->ival = NULL;
- if (staticAutos)
- staticAutos = newNode (NULLOP, staticAutos, work);
- else
- staticAutos = work;
-
- continue;
- }
+ SPEC_SCLS (sym->etype) != S_CODE)
+ {
+ symbol *newSym;
+
+ /* insert the symbol into the symbol table */
+ /* with level = 0 & name = rname */
+ newSym = copySymbol (sym);
+ addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
+
+ /* now lift the code to main */
+ 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",
+ sym->name);
+ }
+ work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
+ list2expr (sym->ival));
+ }
+
+ setAstFileLine (work, sym->fileDef, sym->lineDef);
+
+ sym->ival = NULL;
+ if (staticAutos)
+ staticAutos = newNode (NULLOP, staticAutos, work);
+ else
+ staticAutos = work;
+
+ continue;
+ }
/* 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 {
- if (getNelements(sym->type, sym->ival)>1) {
- werrorfl (filename, sym->lineDef,
- W_EXCESS_INITIALIZERS, "scalar",
- sym->name);
- }
- 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);
- else
- init = work;
- }
+ {
+ initList *ilist = sym->ival;
+
+ while (ilist->type == INIT_DEEP)
+ {
+ ilist = ilist->init.deep;
+ }
+
+ /* update lineno for error msg */
+ filename = sym->fileDef;
+ lineno = sym->lineDef;
+ setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
+
+ if (IS_AGGREGATE (sym->type))
+ {
+ work = initAggregates (sym, sym->ival, NULL);
+ }
+ else
+ {
+ if (getNelements(sym->type, sym->ival)>1)
+ {
+ werrorfl (sym->fileDef, sym->lineDef,
+ W_EXCESS_INITIALIZERS, "scalar",
+ sym->name);
+ }
+ work = newNode ('=', newAst_VALUE (symbolVal (sym)),
+ list2expr (sym->ival));
+ }
+
+ // just to be sure
+ setAstFileLine (work, sym->fileDef, sym->lineDef);
+
+ sym->ival = NULL;
+ if (init)
+ init = newNode (NULLOP, init, work);
+ else
+ init = work;
+ }
}
inInitMode = 0;
return init;
}
}
}
-
+
/*-----------------------------------------------------------------*/
/* stringToSymbol - creates a symbol from a literal string */
/*-----------------------------------------------------------------*/
static int charLbl = 0;
symbol *sym;
set *sp;
- int size;
+ unsigned int size;
// have we heard this before?
- for (sp=statsg->syms; sp; sp=sp->next) {
- sym=sp->item;
- 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);
+ for (sp = statsg->syms; sp; sp = sp->next)
+ {
+ sym = sp->item;
+ 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);
+ }
}
- }
SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
- sym = newSymbol (name, 0); /* make it @ level 0 */
+ sym = newSymbol (name, 0); /* make it @ level 0 */
strncpyz (sym->rname, name, SDCC_NAME_MAX);
/* copy the type from the value passed */
if (noAlloc == 0)
{
/* allocate it */
- addSymChain (sym);
+ addSymChain (&sym);
allocVariables (sym);
}
sym->ival = NULL;
if (action == ALLOCATE)
{
- *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);
+ *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);
}
- else /* action is deallocate */
- deallocLocal (tree->values.sym);
+ else /* action is deallocate */
+ deallocLocal (tree->values.sym);
}
processBlockVars (tree->left, stack, action);
return tree;
}
-
/*-------------------------------------------------------------*/
/* constExprTree - returns TRUE if this tree is a constant */
/* expression */
return TRUE;
}
- cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
- switch (cexpr->type)
+ switch (cexpr->type)
{
case EX_VALUE:
if (IS_AST_LIT_VALUE(cexpr)) {
- // this is a literal
- return TRUE;
+ // 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;
+ // a function's address will never change
+ return TRUE;
}
if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
- // an array's address will never change
- return TRUE;
+ // an array'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
+ 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
//printf(" code space symbol");
- return TRUE;
+ return TRUE;
}
return FALSE;
case EX_LINK:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "unexpected link in expression tree\n");
+ "unexpected link in expression tree\n");
return FALSE;
case EX_OP:
if (cexpr->opval.op==ARRAYINIT) {
- // this is a list of literals
- return TRUE;
+ // this is a list of literals
+ return TRUE;
}
if (cexpr->opval.op=='=') {
- return constExprTree(cexpr->right);
+ return constExprTree(cexpr->right);
}
if (cexpr->opval.op==CAST) {
- // cast ignored, maybe we should throw a warning here?
- return constExprTree(cexpr->right);
+ // cast ignored, maybe we should throw a warning here?
+ return constExprTree(cexpr->right);
}
- if (cexpr->opval.op=='&') {
- return TRUE;
+ if (cexpr->opval.op=='&') {
+ return TRUE;
}
if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
- return FALSE;
+ return FALSE;
}
if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
- return TRUE;
+ return TRUE;
}
return FALSE;
case EX_OPERAND:
}
return FALSE;
}
-
+
/*-----------------------------------------------------------------*/
/* constExprValue - returns the value of a constant expression */
/* or NULL if it is not a constant expression */
value *
constExprValue (ast * cexpr, int check)
{
- cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
/* if this is not a constant then */
if (!IS_LITERAL (cexpr->ftype))
/* then check if this is a literal array
in code segment */
if (SPEC_SCLS (cexpr->etype) == S_CODE &&
- SPEC_CVAL (cexpr->etype).v_char &&
- IS_ARRAY (cexpr->ftype))
- {
- value *val = valFromType (cexpr->ftype);
- SPEC_SCLS (val->etype) = S_LITERAL;
- val->sym = cexpr->opval.val->sym;
- val->sym->type = copyLinkChain (cexpr->ftype);
- val->sym->etype = getSpec (val->sym->type);
- strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
- return val;
- }
+ SPEC_CVAL (cexpr->etype).v_char &&
+ IS_ARRAY (cexpr->ftype))
+ {
+ value *val = valFromType (cexpr->ftype);
+ SPEC_SCLS (val->etype) = S_LITERAL;
+ val->sym = cexpr->opval.val->sym;
+ val->sym->type = copyLinkChain (cexpr->ftype);
+ val->sym->etype = getSpec (val->sym->type);
+ strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
+ return val;
+ }
/* if we are casting a literal value then */
if (IS_AST_OP (cexpr) &&
- cexpr->opval.op == CAST &&
- IS_LITERAL (cexpr->right->ftype))
+ cexpr->opval.op == CAST &&
+ IS_LITERAL (cexpr->right->ftype))
{
- return valCastLiteral (cexpr->ftype,
- floatFromVal (cexpr->right->opval.val));
+ return valCastLiteral (cexpr->ftype,
+ floatFromVal (cexpr->right->opval.val));
}
if (IS_AST_VALUE (cexpr))
{
- return cexpr->opval.val;
+ return cexpr->opval.val;
}
if (check)
- werror (E_CONST_EXPECTED, "found expression");
+ werror (E_CONST_EXPECTED, "found expression");
return NULL;
}
/* 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))
return isLabelInAst (label, tree->right) &&
isLabelInAst (label, tree->left);
-
}
/*-----------------------------------------------------------------*/
/* 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)
+ symbol ** sym, ast ** init, ast ** end)
{
/* the loop is considered countable if the following
/* first check the initExpr */
if (IS_AST_OP (initExpr) &&
- initExpr->opval.op == '=' && /* is assignment */
+ initExpr->opval.op == '=' && /* is assignment */
IS_AST_SYM_VALUE (initExpr->left))
- { /* left is a symbol */
+ { /* left is a symbol */
*sym = AST_SYMBOL (initExpr->left);
*init = initExpr->right;
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))
{
switch (condExpr->opval.op)
- {
- case '<':
- if (IS_AST_SYM_VALUE (condExpr->left) &&
- isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
- IS_AST_LIT_VALUE (condExpr->right))
- {
- *end = condExpr->right;
- break;
- }
- return FALSE;
-
- case '!':
- if (IS_AST_OP (condExpr->left) &&
- condExpr->left->opval.op == '>' &&
- IS_AST_LIT_VALUE (condExpr->left->right) &&
- IS_AST_SYM_VALUE (condExpr->left->left) &&
- isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
- {
-
- *end = newNode ('+', condExpr->left->right,
- newAst_VALUE (constVal ("1")));
- break;
- }
- return FALSE;
-
- default:
- return FALSE;
- }
+ {
+ case '<':
+ if (IS_AST_SYM_VALUE (condExpr->left) &&
+ isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
+ IS_AST_LIT_VALUE (condExpr->right))
+ {
+ *end = condExpr->right;
+ break;
+ }
+ return FALSE;
+
+ case '!':
+ if (IS_AST_OP (condExpr->left) &&
+ condExpr->left->opval.op == '>' &&
+ IS_AST_LIT_VALUE (condExpr->left->right) &&
+ IS_AST_SYM_VALUE (condExpr->left->left) &&
+ isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
+ {
+
+ *end = newNode ('+', condExpr->left->right,
+ newAst_VALUE (constCharVal (1)));
+ break;
+ }
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
}
+ else
+ return FALSE;
/* check loop expression is of the form <sym>++ */
if (!IS_AST_OP (loopExpr))
{
if (loopExpr->left)
- {
- /* pre */
- if (IS_AST_SYM_VALUE (loopExpr->left) &&
- isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
- return TRUE;
+ {
+ /* pre */
+ if (IS_AST_SYM_VALUE (loopExpr->left) &&
+ isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
+ return TRUE;
- }
+ }
else
- {
- /* post */
- if (IS_AST_SYM_VALUE (loopExpr->right) &&
- isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
- return TRUE;
- }
+ {
+ /* post */
+ if (IS_AST_SYM_VALUE (loopExpr->right) &&
+ isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
+ return TRUE;
+ }
}
else
{
/* check for += */
if (loopExpr->opval.op == ADD_ASSIGN)
- {
-
- if (IS_AST_SYM_VALUE (loopExpr->left) &&
- isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
- IS_AST_LIT_VALUE (loopExpr->right) &&
- (int) AST_LIT_VALUE (loopExpr->right) != 1)
- return TRUE;
- }
+ {
+
+ if (IS_AST_SYM_VALUE (loopExpr->left) &&
+ isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
+ IS_AST_LIT_VALUE (loopExpr->right) &&
+ AST_ULONG_VALUE (loopExpr->right) != 1)
+ return TRUE;
+ }
}
return FALSE;
/*-----------------------------------------------------------------*/
/* 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))
if (IS_AST_VALUE (tree))
{
if (IS_AST_SYM_VALUE (tree))
- return isSymbolEqual (AST_SYMBOL (tree), sym);
+ return isSymbolEqual (AST_SYMBOL (tree), sym);
else
- return FALSE;
+ return FALSE;
}
return astHasSymbol (tree->left, sym) ||
/*-----------------------------------------------------------------*/
/* astHasDeref - return true if the ast has an indirect access */
/*-----------------------------------------------------------------*/
-static bool
+static bool
astHasDeref (ast * tree)
{
if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
return FALSE;
if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
-
+
return astHasDeref (tree->left) || astHasDeref (tree->right);
}
/*-----------------------------------------------------------------*/
-/* isConformingBody - the loop body has to conform to a set of rules */
-/* for the loop to be considered reversible read on for rules */
+/* 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)
{
/* we are going to do a pre-order traversal of the
tree && check for the following conditions. (essentially
a set of very shallow tests )
- a) the sym passed does not participate in
- any arithmetic operation
+ a) the sym passed does not participate in any arithmetic operation
b) There are no function calls
c) all jumps are within the body
d) address of loop control variable not taken
- e) if an assignment has a pointer on the
- left hand side make sure right does not have
- loop control variable */
+ e) if an assignment has a pointer on the left hand side make sure
+ right does not have loop control variable
+ */
/* 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;
+ /* array op is commutative -- must check both left & right */
+ if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
+ return FALSE;
}
- return isConformingBody (pbody->right, sym, body);
+ return isConformingBody (pbody->right, sym, body)
+ && isConformingBody (pbody->left, sym, body);
/*------------------------------------------------------------------*/
case PTR_OP:
/* sure we are not sym is not modified */
if (pbody->left &&
- IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
+ IS_AST_SYM_VALUE (pbody->left) &&
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
if (pbody->right &&
- IS_AST_SYM_VALUE (pbody->right) &&
- isSymbolEqual (AST_SYMBOL (pbody->right), sym))
- return FALSE;
+ IS_AST_SYM_VALUE (pbody->right) &&
+ isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+ return FALSE;
return TRUE;
/*------------------------------------------------------------------*/
- case '*': /* can be unary : if right is null then unary operation */
+ case '*': /* can be unary : if right is null then unary operation */
case '+':
case '-':
case '&':
/* if right is NULL then unary operation */
/*------------------------------------------------------------------*/
-/*----------------------------*/
+ /*----------------------------*/
/* address of */
-/*----------------------------*/
+ /*----------------------------*/
if (!pbody->right)
- {
- if (IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
- else
- return isConformingBody (pbody->left, sym, body);
- }
+ {
+ if (IS_AST_SYM_VALUE (pbody->left) &&
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
+ else
+ return isConformingBody (pbody->left, sym, body);
+ }
else
- {
- if (astHasSymbol (pbody->left, sym) ||
- astHasSymbol (pbody->right, sym))
- return FALSE;
- }
+ {
+ if (astHasSymbol (pbody->left, sym) ||
+ astHasSymbol (pbody->right, sym))
+ return FALSE;
+ }
/*------------------------------------------------------------------*/
case '%':
case LEFT_OP:
case RIGHT_OP:
+ case GETABIT:
+ case GETBYTE:
+ case GETWORD:
if (IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
if (IS_AST_SYM_VALUE (pbody->right) &&
- isSymbolEqual (AST_SYMBOL (pbody->right), sym))
- return FALSE;
+ isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+ return FALSE;
return isConformingBody (pbody->left, sym, body) &&
- isConformingBody (pbody->right, sym, body);
+ isConformingBody (pbody->right, sym, body);
case '~':
case '!':
case GETHBIT:
case SWAP:
if (IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
return isConformingBody (pbody->left, sym, body);
/*------------------------------------------------------------------*/
case NE_OP:
case '?':
case ':':
- case SIZEOF: /* evaluate wihout code generation */
+ case SIZEOF: /* evaluate wihout code generation */
if (IS_AST_SYM_VALUE (pbody->left) &&
- isSymbolEqual (AST_SYMBOL (pbody->left), sym))
- return FALSE;
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
if (IS_AST_SYM_VALUE (pbody->right) &&
- isSymbolEqual (AST_SYMBOL (pbody->right), sym))
- return FALSE;
+ isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+ return FALSE;
return isConformingBody (pbody->left, sym, body) &&
- isConformingBody (pbody->right, sym, body);
+ isConformingBody (pbody->right, sym, body);
/*------------------------------------------------------------------*/
case '=':
/* if left has a pointer & right has loop
control variable then we cannot */
if (astHasPointer (pbody->left) &&
- astHasSymbol (pbody->right, sym))
- return FALSE;
+ astHasSymbol (pbody->right, sym))
+ return FALSE;
if (astHasVolatile (pbody->left))
- return FALSE;
+ 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 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;
+ return FALSE;
- if (astHasDeref(pbody->right)) return FALSE;
+ if (astHasDeref(pbody->right))
+ return FALSE;
return isConformingBody (pbody->left, sym, body) &&
- isConformingBody (pbody->right, sym, body);
+ isConformingBody (pbody->right, sym, body);
case MUL_ASSIGN:
case DIV_ASSIGN:
assert ("Parser should not have generated this\n");
/*------------------------------------------------------------------*/
-/*----------------------------*/
+ /*----------------------------*/
/* comma operator */
-/*----------------------------*/
+ /*----------------------------*/
case ',':
return isConformingBody (pbody->left, sym, body) &&
- isConformingBody (pbody->right, sym, body);
+ isConformingBody (pbody->right, sym, body);
/*------------------------------------------------------------------*/
-/*----------------------------*/
+ /*----------------------------*/
/* function call */
-/*----------------------------*/
+ /*----------------------------*/
case CALL:
- /* if local & not passed as paramater then ok */
- if (sym->level && !astHasSymbol(pbody->right,sym))
- return TRUE;
+ /* if local & not passed as parameter &
+ not used to find the function then ok */
+ if (sym->level && !astHasSymbol (pbody->right, sym) &&
+ !astHasSymbol (pbody->left, sym))
+ {
+ return TRUE;
+ }
return FALSE;
/*------------------------------------------------------------------*/
-/*----------------------------*/
+ /*----------------------------*/
/* return statement */
-/*----------------------------*/
+ /*----------------------------*/
case RETURN:
return FALSE;
case GOTO:
if (isLabelInAst (AST_SYMBOL (pbody->left), body))
- return TRUE;
+ return TRUE;
else
- return FALSE;
+ return FALSE;
case SWITCH:
if (astHasSymbol (pbody->left, sym))
- return FALSE;
+ return FALSE;
default:
break;
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
+static bool
isLoopReversible (ast * loop, symbol ** loopCntrl,
- ast ** init, ast ** end)
+ ast ** init, ast ** end)
{
/* if option says don't do it then don't */
if (optimize.noLoopReverse)
[<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
forBody */
if (!isLoopCountable (AST_FOR (loop, initExpr),
- AST_FOR (loop, condExpr),
- AST_FOR (loop, loopExpr),
- loopCntrl, init, end))
+ AST_FOR (loop, condExpr),
+ AST_FOR (loop, loopExpr),
+ loopCntrl, init, end))
return 0;
/* now do some serious checking on the body of the loop
/*-----------------------------------------------------------------*/
/* replLoopSym - replace the loop sym by loop sym -1 */
/*-----------------------------------------------------------------*/
-static void
+static void
replLoopSym (ast * body, symbol * sym)
{
/* reached end */
{
if (isSymbolEqual (AST_SYMBOL (body), sym))
- {
+ {
- body->type = EX_OP;
- body->opval.op = '-';
- body->left = newAst_VALUE (symbolVal (sym));
- body->right = newAst_VALUE (constVal ("1"));
+ body->type = EX_OP;
+ body->opval.op = '-';
+ body->left = newAst_VALUE (symbolVal (sym));
+ body->right = newAst_VALUE (constCharVal (1));
- }
+ }
return;
/* put it together piece by piece */
rloop = newNode (NULLOP,
- createIf (newAst_VALUE (symbolVal (sym)),
- newNode (GOTO,
- newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
- NULL), NULL),
- newNode ('=',
- newAst_VALUE (symbolVal (sym)),
- end));
+ createIf (newAst_VALUE (symbolVal (sym)),
+ newNode (GOTO,
+ newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
+ NULL), NULL),
+ newNode ('=',
+ newAst_VALUE (symbolVal (sym)),
+ end));
replLoopSym (loop->left, sym);
- setAstLineno (rloop, init->lineno);
+ setAstFileLine (rloop, init->filename, init->lineno);
rloop = newNode (NULLOP,
- newNode ('=',
- newAst_VALUE (symbolVal (sym)),
- newNode ('-', end, init)),
- createLabel (AST_FOR (loop, continueLabel),
- newNode (NULLOP,
- loop->left,
- newNode (NULLOP,
- newNode (SUB_ASSIGN,
- newAst_VALUE (symbolVal (sym)),
- newAst_VALUE (constVal ("1"))),
- rloop))));
+ newNode ('=',
+ newAst_VALUE (symbolVal (sym)),
+ newNode ('-', end, init)),
+ createLabel (AST_FOR (loop, continueLabel),
+ newNode (NULLOP,
+ loop->left,
+ newNode (NULLOP,
+ newNode (SUB_ASSIGN,
+ newAst_VALUE (symbolVal (sym)),
+ newAst_VALUE (constCharVal (1))),
+ rloop))));
rloop->lineno=init->lineno;
- return decorateType (rloop, RESULT_CHECK);
+ return decorateType (rloop, RESULT_TYPE_NONE);
}
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;
+ (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
+ {
+ if (IS_LITERAL (RTYPE (tree->right)) !=
+ IS_LITERAL (LTYPE (tree->right)))
+ {
+ 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;
- }
+ (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
+ {
+ if (IS_LITERAL (RTYPE (tree->left)) !=
+ IS_LITERAL (LTYPE (tree->left)))
+ {
+ tree->left->decorated = 0;
+ tree->decorated = 0;
+ *parent = tree;
+ return tree->left;
+ }
+ ret = searchLitOp (tree->left, parent, ops);
+ if (ret)
+ return ret;
+ }
}
return NULL;
}
/*-----------------------------------------------------------------*/
/* getResultFromType */
/*-----------------------------------------------------------------*/
-static RESULT_TYPE
+RESULT_TYPE
getResultTypeFromType (sym_link *type)
{
/* type = getSpec (type); */
- if (IS_BITVAR (type))
+ if (IS_BIT (type))
return RESULT_TYPE_BIT;
if (IS_BITFIELD (type))
- return RESULT_TYPE_CHAR;
+ {
+ int blen = SPEC_BLEN (type);
+
+ if (blen <= 1)
+ return RESULT_TYPE_BIT;
+ if (blen <= 8)
+ return RESULT_TYPE_CHAR;
+ return RESULT_TYPE_INT;
+ }
if (IS_CHAR (type))
return RESULT_TYPE_CHAR;
- if ( IS_INT (type)
- && !IS_LONG (type))
+ if (IS_INT (type) && !IS_LONG (type))
return RESULT_TYPE_INT;
return RESULT_TYPE_OTHER;
}
/*-----------------------------------------------------------------*/
/* addCast - adds casts to a type specified by RESULT_TYPE */
/*-----------------------------------------------------------------*/
-static void
-addCast (ast **tree, RESULT_TYPE resultType, bool upcast)
+static ast *
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
{
sym_link *newLink;
-
+ bool upCasted = FALSE;
+
switch (resultType)
{
+ case RESULT_TYPE_NONE:
+ /* if thing smaller than int must be promoted to int */
+ if (!promote ||
+ getSize (tree->etype) >= INTSIZE)
+ /* promotion not necessary or already an int */
+ return tree;
+ /* char and bits: promote to int */
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ case RESULT_TYPE_BIT:
+ if (!promote ||
+ /* already an int */
+ bitsForType (tree->etype) >= 16 ||
+ /* bit to bit operation: don't promote, the code generators
+ hopefully know everything about promotion rules */
+ bitsForType (tree->etype) == 1)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
case RESULT_TYPE_CHAR:
- if (getSize ((*tree)->etype) <= 1)
- return;
- newLink = newCharLink();
- break;
+ if (IS_CHAR (tree->etype) ||
+ IS_FLOAT(tree->etype) ||
+ IS_FIXED(tree->etype))
+ return tree;
+ newLink = newCharLink();
+ break;
case RESULT_TYPE_INT:
#if 0
- if (getSize ((*tree)->etype) > INTSIZE)
+ if (getSize (tree->etype) > INTSIZE)
{
/* warn ("Loosing significant digits"); */
- return;
- }
+ return;
+ }
#endif
- /* char: promote to int */
- if (!upcast ||
- getSize ((*tree)->etype) >= INTSIZE)
- return;
- newLink = newIntLink();
- break;
+ /* char: promote to int */
+ if (!promote ||
+ getSize (tree->etype) >= INTSIZE)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ case RESULT_TYPE_IFX:
case RESULT_TYPE_OTHER:
- if (!upcast)
- return;
- /* long, float: promote to int */
- if (getSize ((*tree)->etype) >= INTSIZE)
- return;
- newLink = newIntLink();
- break;
+ if (!promote ||
+ /* return type is ifx, long, float: promote char to int */
+ getSize (tree->etype) >= INTSIZE)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
default:
- return;
+ return tree;
}
- (*tree)->decorated = 0;
- *tree = newNode (CAST, newAst_LINK (newLink), *tree);
- /* keep unsigned type */
- SPEC_USIGN ((*tree)->left->opval.lnk) = IS_UNSIGNED ((*tree)->right->etype) ? 1 : 0;
- *tree = decorateType (*tree, resultType);
+ tree->decorated = 0;
+ tree = newNode (CAST, newAst_LINK (newLink), tree);
+ tree->filename = tree->right->filename;
+ tree->lineno = tree->right->lineno;
+ /* keep unsigned type during cast to smaller type,
+ but not when promoting from char to int */
+ if (!upCasted)
+ SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
+ return decorateType (tree, resultType);
}
/*-----------------------------------------------------------------*/
{
switch (tree->opval.op)
{
+ case AND_OP:
+ case OR_OP:
+ case '!':
case '=':
case '?':
case ':':
case '|':
case '^':
- return resultType;
+ case '~':
+ case LEFT_OP:
+ case LABEL:
+ return resultType;
+ case '*':
+ case '+':
+ case '-':
+ if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
+ (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
+ return RESULT_TYPE_NONE;
+ return resultType;
case '&':
- if (!tree->right)
- /* can be unary */
- return RESULT_TYPE_NONE;
- else
- return resultType;
+ if (!tree->right)
+ /* can be unary */
+ return RESULT_TYPE_NONE;
+ else
+ return resultType;
+ case IFX:
+ return RESULT_TYPE_IFX;
default:
- return RESULT_TYPE_NONE;
+ return RESULT_TYPE_NONE;
}
}
{
case '=':
case CAST:
- if (IS_PTR (tree->left->ftype))
- return RESULT_TYPE_NONE;
- else
- return getResultTypeFromType (tree->left->etype);
+ if (IS_PTR (LTYPE (tree)))
+ return RESULT_TYPE_NONE;
+ else
+ return getResultTypeFromType (LETYPE (tree));
case RETURN:
- if (IS_PTR (currFunc->type->next))
- return RESULT_TYPE_NONE;
- else
- return getResultTypeFromType (currFunc->type->next);
+ if (IS_PTR (currFunc->type->next))
+ return RESULT_TYPE_NONE;
+ else
+ return getResultTypeFromType (currFunc->type->next);
+ case '[':
+ if (!IS_ARRAY (LTYPE (tree)))
+ return resultType;
+ if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
+ return RESULT_TYPE_CHAR;
+ return resultType;
default:
- return resultType;
+ return resultType;
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* gatherImplicitVariables: assigns correct type information to */
+/* symbols and values created by replaceAstWithTemporary */
+/* and adds the symbols to the declarations list of the */
+/* innermost block that contains them */
+/*------------------------------------------------------------------*/
+void
+gatherImplicitVariables (ast * tree, ast * block)
+{
+ if (!tree)
+ return;
+
+ if (tree->type == EX_OP && tree->opval.op == BLOCK)
+ {
+ /* keep track of containing scope */
+ block = tree;
}
+ if (tree->type == EX_OP && tree->opval.op == '=' &&
+ tree->left->type == EX_VALUE && tree->left->opval.val->sym)
+ {
+ symbol *assignee = tree->left->opval.val->sym;
+
+ /* special case for assignment to compiler-generated temporary variable:
+ compute type of RHS, and set the symbol's type to match */
+ if (assignee->type == NULL && assignee->infertype) {
+ ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
+
+ if (dtr != tree->right)
+ tree->right = dtr;
+
+ assignee->type = copyLinkChain(TTYPE(dtr));
+ assignee->etype = getSpec(assignee->type);
+ SPEC_SCLS (assignee->etype) = S_AUTO;
+ SPEC_OCLS (assignee->etype) = NULL;
+ SPEC_EXTR (assignee->etype) = 0;
+ SPEC_STAT (assignee->etype) = 0;
+ SPEC_VOLATILE (assignee->etype) = 0;
+ SPEC_ABSA (assignee->etype) = 0;
+
+ wassertl(block != NULL, "implicit variable not contained in block");
+ wassert(assignee->next == NULL);
+ if (block != NULL) {
+ symbol **decl = &(block->values.sym);
+
+ while (*decl) {
+ wassert(*decl != assignee); /* should not already be in list */
+ decl = &( (*decl)->next );
+ }
+
+ *decl = assignee;
+ }
+ }
+ }
+ if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
+ tree->opval.val->type == NULL &&
+ tree->opval.val->sym &&
+ tree->opval.val->sym->infertype)
+ {
+ /* fixup type of value for compiler-inferred temporary var */
+ tree->opval.val->type = tree->opval.val->sym->type;
+ tree->opval.val->etype = tree->opval.val->sym->etype;
+ }
+
+ gatherImplicitVariables(tree->left, block);
+ gatherImplicitVariables(tree->right, block);
}
/*--------------------------------------------------------------------*/
/* decorateType - compute type for this tree, also does type checking.*/
/* This is done bottom up, since type has to flow upwards. */
-/* resultType flows top-down and forces e.g. char-arithmetik, if the */
+/* resultType flows top-down and forces e.g. char-arithmetic, if the */
/* result is a char and the operand(s) are int's. */
/* It also does constant folding, and parameter checking. */
/*--------------------------------------------------------------------*/
/*----------------------------*/
/* leaf has been reached */
/*----------------------------*/
- lineno=tree->lineno;
+ filename = tree->filename;
+ lineno = tree->lineno;
/* if this is of type value */
/* just get the type */
if (tree->type == EX_VALUE)
{
-
if (IS_LITERAL (tree->opval.val->etype))
- {
-
- /* if this is a character array then declare it */
- if (IS_ARRAY (tree->opval.val->type))
- tree->opval.val = stringToSymbol (tree->opval.val);
+ {
+ /* if this is a character array then declare it */
+ if (IS_ARRAY (tree->opval.val->type))
+ tree->opval.val = stringToSymbol (tree->opval.val);
- /* otherwise just copy the type information */
- COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
- return tree;
- }
+ /* otherwise just copy the type information */
+ COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
+ return tree;
+ }
if (tree->opval.val->sym)
- {
- /* if the undefined flag is set then give error message */
- if (tree->opval.val->sym->undefined)
- {
- werror (E_ID_UNDEF, tree->opval.val->sym->name);
- /* assume int */
- TTYPE (tree) = TETYPE (tree) =
- tree->opval.val->type = tree->opval.val->sym->type =
- tree->opval.val->etype = tree->opval.val->sym->etype =
- copyLinkChain (INTTYPE);
- }
- else
- {
-
- /* if 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;
- }
- }
- }
+ {
+ /* if the undefined flag is set then give error message */
+ if (tree->opval.val->sym->undefined)
+ {
+ werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
+ /* assume int */
+ TTYPE (tree) = TETYPE (tree) =
+ tree->opval.val->type = tree->opval.val->sym->type =
+ tree->opval.val->etype = tree->opval.val->sym->etype =
+ copyLinkChain (INTTYPE);
+ }
+ else if (tree->opval.val->sym->implicit)
+ {
+ /* if implicit i.e. struct/union member then no type */
+ TTYPE (tree) = TETYPE (tree) = NULL;
+ }
+ else
+ {
+ /* copy the type from the value into the ast */
+ COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
+
+ /* and mark the symbol as referenced */
+ tree->opval.val->sym->isref = 1;
+ }
+ }
+ else
+ wassert(0); /* unreached: all values are literals or symbols */
return tree;
}
if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
{
if (tree->left && tree->left->type == EX_OPERAND
- && (tree->left->opval.op == INC_OP
- || tree->left->opval.op == DEC_OP)
- && tree->left->left)
- {
- tree->left->right = tree->left->left;
- tree->left->left = NULL;
- }
+ && (tree->left->opval.op == INC_OP
+ || tree->left->opval.op == DEC_OP)
+ && tree->left->left)
+ {
+ tree->left->right = tree->left->left;
+ tree->left->left = NULL;
+ }
if (tree->right && tree->right->type == EX_OPERAND
- && (tree->right->opval.op == INC_OP
- || tree->right->opval.op == DEC_OP)
- && tree->right->left)
- {
- tree->right->right = tree->right->left;
- tree->right->left = NULL;
- }
+ && (tree->right->opval.op == INC_OP
+ || tree->right->opval.op == DEC_OP)
+ && tree->right->left)
+ {
+ tree->right->right = tree->right->left;
+ tree->right->left = NULL;
+ }
}
#endif
/* Before decorating the left branch we've to decide in dependence
upon tree->opval.op, if resultType can be propagated */
- if (getenv ("SDCC_NEWTYPEFLOW"))
- resultTypeProp = resultTypePropagate (tree, resultType);
+ resultTypeProp = resultTypePropagate (tree, resultType);
+
+ if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
+ dtl = decorateType (tree->left, RESULT_TYPE_IFX);
else
- resultTypeProp = RESULT_TYPE_NONE; /* provide initialization */
+ dtl = decorateType (tree->left, resultTypeProp);
- dtl = decorateType (tree->left, resultTypeProp);
+ /* if an array node, we may need to swap branches */
+ if (tree->opval.op == '[')
+ {
+ /* determine which is the array & which the index */
+ if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
+ IS_INTEGRAL (LTYPE (tree)))
+ {
+ ast *tempTree = tree->left;
+ tree->left = tree->right;
+ tree->right = tempTree;
+ }
+ }
/* After decorating the left branch there's type information available
in tree->left->?type. If the op is e.g. '=' we extract the type
information from there and propagate it to the right branch. */
- if (getenv ("SDCC_NEWTYPEFLOW"))
- resultTypeProp = getLeftResultType (tree, resultTypeProp);
-
- /* delay right side for '?' operator since conditional macro expansions
- might rely on this */
- dtr = tree->opval.op == '?' ? tree->right :
- decorateType (tree->right, resultTypeProp);
+ resultTypeProp = getLeftResultType (tree, resultTypeProp);
+
+ switch (tree->opval.op)
+ {
+ case '?':
+ /* delay right side for '?' operator since conditional macro
+ expansions might rely on this */
+ dtr = tree->right;
+ break;
+ case CALL:
+ /* decorate right side for CALL (parameter list) in processParms();
+ there is resultType available */
+ dtr = tree->right;
+ break;
+ case SIZEOF:
+ /* don't allocate string if it is a sizeof argument */
+ ++noAlloc;
+ dtr = decorateType (tree->right, resultTypeProp);
+ --noAlloc;
+ break;
+ default:
+ dtr = decorateType (tree->right, resultTypeProp);
+ break;
+ }
/* this is to take care of situations
when the tree gets rewritten */
tree->right = dtr;
if ((dtl && dtl->isError) || (dtr && dtr->isError))
return tree;
-
- if (!getenv ("SDCC_NEWTYPEFLOW"))
- {
- if (IS_AST_OP(tree) &&
- (tree->opval.op == CAST || tree->opval.op == '=') &&
- (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
- (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) &&
- (tree->right->opval.op == LEFT_OP ||
- tree->right->opval.op == '*' ||
- tree->right->opval.op == '+' ||
- tree->right->opval.op == '-') &&
- tree->right->right) {
- /* we should cast an operand instead of the result */
- tree->right->decorated = 0;
- tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
- tree->right->left);
- tree->right = decorateType(tree->right, RESULT_CHECK);
- }
- }
- }
}
/* depending on type of operator do */
switch (tree->opval.op)
{
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* array node */
- /*----------------------------*/
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* array node */
+ /*----------------------------*/
case '[':
- /* determine which is the array & which the index */
- if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree)))
- {
-
- ast *tempTree = tree->left;
- tree->left = tree->right;
- tree->right = tempTree;
- }
-
/* first check if this is a array or a pointer */
if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
- {
- werror (E_NEED_ARRAY_PTR, "[]");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
+ goto errorTreeReturn;
+ }
/* check if the type of the idx */
if (!IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_IDX_NOT_INT);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
+ goto errorTreeReturn;
+ }
/* if the left is an rvalue then error */
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "array access");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
+ goto errorTreeReturn;
+ }
+
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
+ int arraySize = DCL_ELEM (LTYPE (tree));
+ if (arraySize && arrayIndex >= arraySize)
+ {
+ werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
+ }
+ }
+
RRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
+ SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
return tree;
/*------------------------------------------------------------------*/
case '.':
/* if this is not a structure */
if (!IS_STRUCT (LTYPE (tree)))
- {
- werror (E_STRUCT_UNION, ".");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
+ goto errorTreeReturn;
+ }
TTYPE (tree) = structElemType (LTYPE (tree),
- (tree->right->type == EX_VALUE ?
- tree->right->opval.val : NULL));
+ (tree->right->type == EX_VALUE ?
+ tree->right->opval.val : NULL));
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
case PTR_OP:
/* if not pointer to a structure */
if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
- {
- werror (E_PTR_REQD);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
+ goto errorTreeReturn;
+ }
if (!IS_STRUCT (LTYPE (tree)->next))
- {
- werror (E_STRUCT_UNION, "->");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
+ goto errorTreeReturn;
+ }
TTYPE (tree) = structElemType (LTYPE (tree)->next,
- (tree->right->type == EX_VALUE ?
- tree->right->opval.val : NULL));
+ (tree->right->type == EX_VALUE ?
+ tree->right->opval.val : NULL));
TETYPE (tree) = getSpec (TTYPE (tree));
/* adjust the storage class */
switch (DCL_TYPE(tree->left->ftype)) {
case POINTER:
- SPEC_SCLS(TETYPE(tree)) = S_DATA;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
+ break;
case FPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XDATA;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+ break;
case CPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_CODE;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_CODE;
+ break;
case GPOINTER:
- SPEC_SCLS (TETYPE (tree)) = 0;
- break;
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
case PPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+ break;
case IPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_IDATA;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+ break;
case EEPPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
- break;
+ SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
+ break;
case UPOINTER:
- SPEC_SCLS (TETYPE (tree)) = 0;
- break;
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
case ARRAY:
case FUNCTION:
- break;
+ 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 */
*/
symbol *sym;
symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
- AST_SYMBOL(tree->right));
+ AST_SYMBOL(tree->right));
sym = newSymbol(genSymName (0), 0);
sym->type = TTYPE (tree);
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;
/*------------------------------------------------------------------*/
case INC_OP:
case DEC_OP:
{
- sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
- COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
+ sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
+ COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
- werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
- if (tree->right)
- RLVAL (tree) = 1;
- else
- LLVAL (tree) = 1;
- return tree;
+ if (tree->right)
+ RLVAL (tree) = 1;
+ else
+ LLVAL (tree) = 1;
+ return tree;
}
/*------------------------------------------------------------------*/
/*----------------------------*/
/* bitwise and */
/*----------------------------*/
- case '&': /* can be unary */
+ case '&': /* can be unary */
/* if right is NULL then unary operation */
- if (tree->right) /* not an unary operation */
- {
-
- if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, ",");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
-
- /* if they are both literal */
- if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)), '&');
-
- tree->right = tree->left = NULL;
- TETYPE (tree) = tree->opval.val->etype;
- TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
-
- /* see if this is a GETHBIT operation if yes
- then return that */
- {
- ast *otree = optimizeGetHbit (tree);
-
- if (otree != tree)
- return decorateType (otree, RESULT_CHECK);
- }
-
- if (getenv ("SDCC_NEWTYPEFLOW"))
- {
- addCast (&tree->left, resultType, FALSE);
- addCast (&tree->right, resultType, FALSE);
- }
- TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
- TETYPE (tree) = getSpec (TTYPE (tree));
+ if (tree->right) /* not an unary operation */
+ {
+
+ if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+ werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, ",");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
+
+ /* if they are both literal */
+ if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)), '&');
+
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = tree->opval.val->etype;
+ TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
+
+ /* see if this is a GETHBIT operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetHbit (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETABIT operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetAbit (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETBYTE operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetByte (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETWORD operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetWord (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
/* 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, RESULT_CHECK);
- }
- }
-
- LRVAL (tree) = RRVAL (tree) = 1;
-
- return 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 an and-tree then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "&");
+ if (litTree)
+ {
+ DEBUG_CF("&")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in litTree are literal now */
+ decorateType (parent, resultType);
+ }
+ }
+
+ LRVAL (tree) = RRVAL (tree) = 1;
+
+ TTYPE (tree) = computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op);
+ TETYPE (tree) = getSpec (TTYPE (tree));
+
+ return tree;
+ }
/*------------------------------------------------------------------*/
/*----------------------------*/
p = newLink (DECLARATOR);
/* if bit field then error */
if (IS_BITVAR (tree->left->etype))
- {
- werror (E_ILLEGAL_ADDR, "address of bit variable");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
+ goto errorTreeReturn;
+ }
if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
- {
- werror (E_ILLEGAL_ADDR, "address of register variable");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
+ goto errorTreeReturn;
+ }
if (IS_FUNC (LTYPE (tree)))
- {
- // this ought to be ignored
- return (tree->left);
- }
+ {
+ // this ought to be ignored
+ return (tree->left);
+ }
if (IS_LITERAL(LTYPE(tree)))
- {
- werror (E_ILLEGAL_ADDR, "address of literal");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
+ goto errorTreeReturn;
+ }
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "address of");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
+ goto errorTreeReturn;
+ }
if (!LETYPE (tree))
DCL_TYPE (p) = POINTER;
else if (SPEC_SCLS (tree->left->etype) == S_CODE)
- DCL_TYPE (p) = CPOINTER;
+ DCL_TYPE (p) = CPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
- DCL_TYPE (p) = FPOINTER;
+ DCL_TYPE (p) = FPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
- DCL_TYPE (p) = PPOINTER;
+ DCL_TYPE (p) = PPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
- DCL_TYPE (p) = IPOINTER;
+ DCL_TYPE (p) = IPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
- DCL_TYPE (p) = EEPPOINTER;
+ DCL_TYPE (p) = EEPPOINTER;
else if (SPEC_OCLS(tree->left->etype))
- DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
+ DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
else
- DCL_TYPE (p) = POINTER;
+ DCL_TYPE (p) = POINTER;
if (IS_AST_SYM_VALUE (tree->left))
- {
- AST_SYMBOL (tree->left)->addrtaken = 1;
- AST_SYMBOL (tree->left)->allocreq = 1;
- }
+ {
+ AST_SYMBOL (tree->left)->addrtaken = 1;
+ AST_SYMBOL (tree->left)->allocreq = 1;
+ }
p->next = LTYPE (tree);
TTYPE (tree) = p;
&& 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),
+ 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;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->type = EX_VALUE;
+ tree->values.literalFromCast = 1;
}
#endif
/* bitwise or */
/*----------------------------*/
case '|':
- /* if the rewrite succeeds then don't go any furthur */
+ /* if the rewrite succeeds then don't go any further */
{
- ast *wtree = optimizeRRCRLC (tree);
- if (wtree != tree)
- return decorateType (wtree, RESULT_CHECK);
-
- wtree = optimizeSWAP (tree);
- if (wtree != tree)
- return decorateType (wtree, RESULT_CHECK);
+ 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);
}
/* if left is a literal exchange left & right */
if (IS_LITERAL (LTYPE (tree)))
- {
- ast *tTree = tree->left;
- tree->left = tree->right;
- tree->right = tTree;
- }
+ {
+ 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 */
+ /* we can find a 2nd literal in an 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, RESULT_CHECK);
- }
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "|");
+ if (litTree)
+ {
+ DEBUG_CF("|")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in tTree are literal now */
+ decorateType (parent, resultType);
+ }
}
/* fall through */
/*----------------------------*/
case '^':
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, ",");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+ werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, ",");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
- /* if they are both literal then */
- /* rewrite the tree */
+ /* if they are both literal then rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
- tree->opval.op);
- tree->right = tree->left = NULL;
- TETYPE (tree) = tree->opval.val->etype;
- TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)),
+ tree->opval.op);
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = tree->opval.val->etype;
+ 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;
- }
+ {
+ 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)) &&
tree->opval.op == '^') /* the same source is used by 'bitwise or' */
- {
- 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, RESULT_CHECK);
- }
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "^");
+ if (litTree)
+ {
+ DEBUG_CF("^")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in litTree are literal now */
+ decorateType (parent, resultType);
+ }
}
LRVAL (tree) = RRVAL (tree) = 1;
- if (getenv ("SDCC_NEWTYPEFLOW"))
- {
- addCast (&tree->left, resultType, FALSE);
- addCast (&tree->right, resultType, FALSE);
- }
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
+
+ TTYPE (tree) = computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op);
+ TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
/*----------------------------*/
case '/':
if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
- {
- werror (E_INVALID_OP, "divide");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valDiv (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valDiv (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
LRVAL (tree) = RRVAL (tree) = 1;
+
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
/* 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, RESULT_CHECK);
- }
- else
- {
- /* litTree->left is literal: no gcse possible.
- We can't call decorateType(parent, RESULT_CHECK), because
- this would cause an infinit loop. */
- parent->decorated = 1;
- decorateType (litTree, RESULT_CHECK);
- }
- }
- }
+ && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "/");
+ if (litTree)
+ {
+ if (IS_LITERAL (RTYPE (litTree)))
+ {
+ /* foo_div */
+ DEBUG_CF("div r")
+ litTree->right = newNode ('*',
+ litTree->right,
+ copyAst (tree->right));
+ litTree->right->filename = tree->filename;
+ litTree->right->lineno = tree->lineno;
+
+ tree->right->opval.val = constCharVal (1);
+ decorateType (parent, resultType);
+ }
+ else
+ {
+ /* litTree->left is literal: no gcse possible.
+ We can't call decorateType(parent, RESULT_TYPE_NONE), because
+ this would cause an infinit loop. */
+ parent->decorated = 1;
+ decorateType (litTree, resultType);
+ }
+ }
+ }
return tree;
/*----------------------------*/
case '%':
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, ",");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+ werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, ",");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valMod (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valMod (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* address dereference */
/*----------------------------*/
- case '*': /* can be unary : if right is null then unary operation */
+ case '*': /* can be unary : if right is null then unary operation */
if (!tree->right)
- {
- if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
- {
- werror (E_PTR_REQD);
- goto errorTreeReturn;
- }
-
- if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "pointer deref");
- goto errorTreeReturn;
- }
- if (IS_ADDRESS_OF_OP(tree->left))
+ {
+ if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
+ goto errorTreeReturn;
+ }
+
+ if (LRVAL (tree))
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
+ goto errorTreeReturn;
+ }
+ 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;
+ 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 ARRAY:
- case FUNCTION:
- break;
- }
- return tree;
- }
+ 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;
+ }
/*------------------------------------------------------------------*/
/*----------------------------*/
/* multiplication */
/*----------------------------*/
if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
- {
- werror (E_INVALID_OP, "multiplication");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valMult (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valMult (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (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;
- }
+ {
+ 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 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, RESULT_CHECK);
- }
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "*");
+ if (litTree)
+ {
+ DEBUG_CF("mul")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in litTree are literal now */
+ decorateType (parent, resultType);
+ }
}
LRVAL (tree) = RRVAL (tree) = 1;
- if (!getenv ("SDCC_NEWTYPEFLOW"))
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- TRUE));
- else
- {
- addCast (&tree->left, resultType, FALSE);
- addCast (&tree->right, resultType, FALSE);
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
- }
-
+ tree->left = addCast (tree->left, resultTypeProp, FALSE);
+ tree->right = addCast (tree->right, resultTypeProp, FALSE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+
return tree;
/*------------------------------------------------------------------*/
case '+':
/* if unary plus */
if (!tree->right)
- {
- if (!IS_ARITHMETIC (LTYPE (tree)))
- {
- werror (E_UNARY_OP, '+');
- goto errorTreeReturn;
- }
-
- /* if left is a literal then do it */
- if (IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valFromType (LETYPE (tree));
- tree->left = NULL;
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
- LRVAL (tree) = 1;
- COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
- return tree;
- }
-
+ {
+ if (!IS_ARITHMETIC (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
+ goto errorTreeReturn;
+ }
+
+ /* if left is a literal then do it */
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valFromType (LETYPE (tree));
+ tree->left = NULL;
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
+ LRVAL (tree) = 1;
+ COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
+ return tree;
+ }
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* addition */
/* this is not a unary operation */
/* if both pointers then problem */
if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
- (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
- {
- werror (E_PTR_PLUS_PTR);
- goto errorTreeReturn;
- }
+ (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
+ goto errorTreeReturn;
+ }
if (!IS_ARITHMETIC (LTYPE (tree)) &&
- !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
- {
- werror (E_PLUS_INVALID, "+");
- goto errorTreeReturn;
- }
+ !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
+ goto errorTreeReturn;
+ }
if (!IS_ARITHMETIC (RTYPE (tree)) &&
- !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
- {
- werror (E_PLUS_INVALID, "+");
- goto errorTreeReturn;
- }
+ !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valPlus (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
+ tree->opval.val = valPlus (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
/* if the right is a pointer or left is a literal
xchange left & right */
if (IS_ARRAY (RTYPE (tree)) ||
- IS_PTR (RTYPE (tree)) ||
- IS_LITERAL (LTYPE (tree)))
- {
- ast *tTree = tree->left;
- tree->left = tree->right;
- tree->right = tTree;
- }
+ IS_PTR (RTYPE (tree)) ||
+ IS_LITERAL (LTYPE (tree)))
+ {
+ ast *tTree = tree->left;
+ tree->left = tree->right;
+ 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, RESULT_CHECK);
- }
- }
+ {
+ ast *litTree, *parent;
+ litTree = searchLitOp (tree, &parent, "+-");
+ if (litTree)
+ {
+ if (litTree->opval.op == '+')
+ {
+ /* foo_aa */
+ DEBUG_CF("+ 1 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)))
+ {
+ DEBUG_CF("+ 2 ASR")
+ /* foo_asr */
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ }
+ else
+ {
+ DEBUG_CF("+ 3 ASL")
+ /* foo_asl */
+ ast *tTree = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ litTree->opval.op = '+';
+ tree->opval.op = '-';
+ }
+ }
+ decorateType (parent, resultType);
+ }
+ }
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) =
- LTYPE (tree));
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ LTYPE (tree));
else
- if (!getenv ("SDCC_NEWTYPEFLOW"))
+ {
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
- else
- {
- addCast (&tree->left, resultType, TRUE);
- addCast (&tree->right, resultType, TRUE);
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
- }
-
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+ }
+
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* unary '-' */
/*----------------------------*/
- case '-': /* can be unary */
+ case '-': /* can be unary */
/* if right is null then unary */
if (!tree->right)
- {
-
- if (!IS_ARITHMETIC (LTYPE (tree)))
- {
- werror (E_UNARY_OP, tree->opval.op);
- goto errorTreeReturn;
- }
-
- /* if left is a literal then do it */
- if (IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- 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;
- }
- LRVAL (tree) = 1;
- TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
- return tree;
- }
+ {
+
+ if (!IS_ARITHMETIC (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
+ goto errorTreeReturn;
+ }
+
+ /* if left is a literal then do it */
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
+ tree->left = NULL;
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ NULL,
+ resultType,
+ tree->opval.op));
+ LRVAL (tree) = 1;
+ return tree;
+ }
/*------------------------------------------------------------------*/
/*----------------------------*/
/*----------------------------*/
if (!(IS_PTR (LTYPE (tree)) ||
- IS_ARRAY (LTYPE (tree)) ||
- IS_ARITHMETIC (LTYPE (tree))))
- {
- werror (E_PLUS_INVALID, "-");
- goto errorTreeReturn;
- }
+ IS_ARRAY (LTYPE (tree)) ||
+ IS_ARITHMETIC (LTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
+ goto errorTreeReturn;
+ }
if (!(IS_PTR (RTYPE (tree)) ||
- IS_ARRAY (RTYPE (tree)) ||
- IS_ARITHMETIC (RTYPE (tree))))
- {
- werror (E_PLUS_INVALID, "-");
- goto errorTreeReturn;
- }
+ IS_ARRAY (RTYPE (tree)) ||
+ IS_ARITHMETIC (RTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
+ goto errorTreeReturn;
+ }
if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
- !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
- IS_INTEGRAL (RTYPE (tree))))
- {
- werror (E_PLUS_INVALID, "-");
- goto errorTreeReturn;
- }
+ !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
+ IS_INTEGRAL (RTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valMinus (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
+ tree->opval.val = valMinus (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
/* if the left & right are equal then zero */
if (isAstEqual (tree->left, tree->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;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->left = tree->right = NULL;
+ tree->opval.val = constCharVal (0);
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
/* if both of them are pointers or arrays then */
/* the result is going to be an integer */
if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
- (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
- TETYPE (tree) = TTYPE (tree) = newIntLink ();
+ (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
+ TETYPE (tree) = TTYPE (tree) = newIntLink ();
else
- /* if only the left is a pointer */
- /* then result is a pointer */
+ /* if only the left is a pointer */
+ /* then result is a pointer */
if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
- TETYPE (tree) = getSpec (TTYPE (tree) =
- LTYPE (tree));
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ LTYPE (tree));
else
- if (!getenv ("SDCC_NEWTYPEFLOW"))
+ {
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
+
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
- else
- {
- addCast (&tree->left, resultType, TRUE);
- addCast (&tree->right, resultType, TRUE);
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
- }
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+ }
LRVAL (tree) = RRVAL (tree) = 1;
/* 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, RESULT_CHECK);
- }
- }
+ && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
+ {
+ ast *litTree, *litParent;
+ litTree = searchLitOp (tree, &litParent, "+-");
+ if (litTree)
+ {
+ if (litTree->opval.op == '+')
+ {
+ /* foo_sa */
+ DEBUG_CF("- 1 SA")
+ ast *tTree = litTree->left;
+ litTree->left = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ tree->opval.op = '+';
+ litTree->opval.op = '-';
+ }
+ else if (litTree->opval.op == '-')
+ {
+ if (IS_LITERAL (RTYPE (litTree)))
+ {
+ /* foo_ssr */
+ DEBUG_CF("- 2 SSR")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = litParent->left;
+ litParent->left = tTree;
+ litTree->opval.op = '+';
+
+ tree->decorated = 0;
+ decorateType (tree, resultType);
+ }
+ else
+ {
+ /* foo_ssl */
+ DEBUG_CF("- 3 SSL")
+ ast *tTree = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ }
+ }
+ decorateType (litParent, resultType);
+ }
+ }
return tree;
/*------------------------------------------------------------------*/
case '~':
/* can be only integral type */
if (!IS_INTEGRAL (LTYPE (tree)))
- {
- werror (E_UNARY_OP, tree->opval.op);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
+ goto errorTreeReturn;
+ }
/* if left is a literal then do it */
if (IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valComplement (valFromType (LETYPE (tree)));
- tree->left = NULL;
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valComplement (valFromType (LETYPE (tree)));
+ tree->left = NULL;
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return addCast (tree, resultTypeProp, TRUE);
+ }
+
+ if (resultType == RESULT_TYPE_BIT &&
+ IS_UNSIGNED (tree->left->etype) &&
+ getSize (tree->left->etype) < INTSIZE)
+ {
+ /* promotion rules are responsible for this strange result:
+ bit -> int -> ~int -> bit
+ uchar -> int -> ~int -> bit
+ */
+ werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
+
+ /* optimize bit-result, even if we optimize a buggy source */
+ tree->type = EX_VALUE;
+ tree->opval.val = constCharVal (1);
+ }
+ else
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
LRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
return tree;
case '!':
/* can be pointer */
if (!IS_ARITHMETIC (LTYPE (tree)) &&
- !IS_PTR (LTYPE (tree)) &&
- !IS_ARRAY (LTYPE (tree)))
- {
- werror (E_UNARY_OP, tree->opval.op);
- goto errorTreeReturn;
- }
+ !IS_PTR (LTYPE (tree)) &&
+ !IS_ARRAY (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
+ goto errorTreeReturn;
+ }
+
+ /* if left is another '!' */
+ if (IS_AST_NOT_OPER (tree->left))
+ {
+ if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
+ {
+ /* replace double '!!X' by 'X' */
+ return tree->left->left;
+ }
+ /* remove double '!!X' by 'X ? 1 : 0' */
+ tree->opval.op = '?';
+ tree->left = tree->left->left;
+ tree->right = newNode (':',
+ newAst_VALUE (constCharVal (1)),
+ newAst_VALUE (constCharVal (0)));
+ tree->right->filename = tree->filename;
+ 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)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valNot (valFromType (LETYPE (tree)));
- tree->left = NULL;
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valNot (valFromType (LETYPE (tree)));
+ tree->left = NULL;
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
LRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
return tree;
/*------------------------------------------------------------------*/
return tree;
case GETHBIT:
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ case GETABIT:
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+ return tree;
+
+ case GETBYTE:
+ TTYPE (tree) = TETYPE (tree) = newCharLink();
+ return tree;
+
+ case GETWORD:
+ TTYPE (tree) = TETYPE (tree) = newIntLink();
return tree;
case LEFT_OP:
case RIGHT_OP:
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
- {
- werror (E_SHIFT_OP_INVALID);
- werror (W_CONTINUE, "left & right types are ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, ",");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
+ werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, ",");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
+
+ /* make smaller type only if it's a LEFT_OP */
+ if (tree->opval.op == LEFT_OP)
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valShift (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
- (tree->opval.op == LEFT_OP ? 1 : 0));
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valShift (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)),
+ (tree->opval.op == LEFT_OP ? 1 : 0));
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
+
+ /* see if this is a GETBYTE operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetByte (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETWORD operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetWord (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
LRVAL (tree) = RRVAL (tree) = 1;
if (tree->opval.op == LEFT_OP)
- {
- if (!getenv ("SDCC_NEWTYPEFLOW"))
- /* promote char to int */
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- LTYPE (tree), /* no, not RTYPE! */
- TRUE));
- else
- {
- addCast (&tree->left, resultType, TRUE);
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
- }
- }
+ {
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ NULL,
+ resultType,
+ tree->opval.op));
+ }
else /* RIGHT_OP */
- {
- /* no promotion necessary */
- TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
- if (IS_LITERAL (TTYPE (tree)))
- SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
- }
+ {
+ /* no promotion necessary */
+ TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+ if (IS_LITERAL (TTYPE (tree)))
+ SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+ }
/* if only the right side is a literal & we are
shifting more than size of the left operand then zero */
if (IS_LITERAL (RTYPE (tree)) &&
- ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
- (getSize (TETYPE (tree)) * 8))
- {
- if (tree->opval.op==LEFT_OP ||
- (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
- {
- lineno=tree->lineno;
- werror (W_SHIFT_CHANGED,
- (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;
- }
- }
+ ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
+ (getSize (TETYPE (tree)) * 8))
+ {
+ if (tree->opval.op==LEFT_OP ||
+ (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
+ (tree->opval.op == LEFT_OP ? "left" : "right"));
+ tree->type = EX_VALUE;
+ tree->left = tree->right = NULL;
+ tree->opval.val = constCharVal (0);
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
+ }
return tree;
/*----------------------------*/
/* casting */
/*----------------------------*/
- case CAST: /* change the type */
+ case CAST: /* change the type */
/* cannot cast to an aggregate type */
if (IS_AGGREGATE (LTYPE (tree)))
- {
- werror (E_CAST_ILLEGAL);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
+ goto errorTreeReturn;
+ }
/* make sure the type is complete and sane */
+ 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)
+ {
+ /* mark that the explicit cast has been removed,
+ * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
+ tree->right->values.removedCast = 1;
+ return tree->right;
+ }
+
/* If code memory is read only, then pointers to code memory */
/* implicitly point to constants -- make this explicit */
{
- sym_link *t = LTYPE(tree);
- while (t && t->next)
- {
- if (IS_CODEPTR(t) && port->mem.code_ro)
- {
- if (IS_SPEC(t->next))
- SPEC_CONST (t->next) = 1;
- else
- DCL_PTR_CONST (t->next) = 1;
- }
- t = t->next;
+ sym_link *t = LTYPE(tree);
+ while (t && t->next)
+ {
+ if (IS_CODEPTR(t) && port->mem.code_ro)
+ {
+ if (IS_SPEC(t->next))
+ SPEC_CONST (t->next) = 1;
+ else
+ DCL_PTR_CONST (t->next) = 1;
+ }
+ t = t->next;
}
}
#if 0
/* if the right is a literal replace the tree */
- if (IS_LITERAL (RETYPE (tree))) {
- if (!IS_PTR (LTYPE (tree))) {
- tree->type = EX_VALUE;
- tree->opval.val =
- valCastLiteral (LTYPE (tree),
- floatFromVal (valFromType (RETYPE (tree))));
- tree->left = NULL;
- tree->right = NULL;
- TTYPE (tree) = tree->opval.val->type;
- tree->values.literalFromCast = 1;
- } 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);
- TTYPE(tree) = newLink(DECLARATOR);
- DCL_TYPE(TTYPE(tree)) = FPOINTER;
- TTYPE(tree)->next = rest;
- tree->left->opval.lnk = TTYPE(tree);
- LRVAL (tree) = 1;
- } else {
- TTYPE (tree) = LTYPE (tree);
- LRVAL (tree) = 1;
- }
- } else {
- TTYPE (tree) = LTYPE (tree);
- LRVAL (tree) = 1;
- }
+ if (IS_LITERAL (RETYPE (tree)))
+ {
+ if (!IS_PTR (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val =
+ valCastLiteral (LTYPE (tree),
+ floatFromVal (valFromType (RETYPE (tree))));
+ tree->left = NULL;
+ tree->right = NULL;
+ TTYPE (tree) = tree->opval.val->type;
+ tree->values.literalFromCast = 1;
+ }
+ else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
+ ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */
+ {
+ sym_link *rest = LTYPE(tree)->next;
+ werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
+ TTYPE(tree) = newLink(DECLARATOR);
+ DCL_TYPE(TTYPE(tree)) = FPOINTER;
+ TTYPE(tree)->next = rest;
+ tree->left->opval.lnk = TTYPE(tree);
+ LRVAL (tree) = 1;
+ }
+ else
+ {
+ TTYPE (tree) = LTYPE (tree);
+ LRVAL (tree) = 1;
+ }
+ }
+ else
+ {
+ TTYPE (tree) = LTYPE (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);
- }
+ IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
+ strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
+ {
+ werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
+ SPEC_STRUCT(LETYPE(tree))->tag);
+ }
#endif
if (IS_ADDRESS_OF_OP(tree->right)
&& IS_AST_SYM_VALUE (tree->right->left)
- && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
+ && 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);
- tree->type = EX_VALUE;
- tree->opval.val =
- valCastLiteral (LTYPE (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;
- tree->values.literalFromCast = 1;
- return tree;
- }
+ if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) || TARGET_IS_PIC16) )
+ {
+ switch (SPEC_SCLS (sym->etype))
+ {
+ case S_CODE:
+ gptype = GPTYPE_CODE;
+ break;
+ case S_XDATA:
+ gptype = GPTYPE_FAR;
+ break;
+ case S_DATA:
+ case S_IDATA:
+ gptype = GPTYPE_NEAR;
+ break;
+ case S_PDATA:
+ gptype = GPTYPE_XSTACK;
+ break;
+ default:
+ gptype = 0;
+
+ if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
+ gptype = GPTYPE_NEAR;
+ }
+ addr |= gptype << (8*(GPTRSIZE - 1));
+ }
+
+ tree->type = EX_VALUE;
+ tree->opval.val = valCastLiteral (LTYPE (tree), addr);
+ TTYPE (tree) = tree->opval.val->type;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->values.literalFromCast = 1;
+ return tree;
+ }
/* handle offsetof macro: */
/* #define offsetof(TYPE, MEMBER) \ */
&& 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)))
+ && IS_AST_LIT_VALUE(tree->right->left->left->right))
+ {
+ symbol *element = getStructElement (
+ SPEC_STRUCT (LETYPE(tree->right->left)),
+ AST_SYMBOL(tree->right->left->right)
);
- TTYPE (tree) = tree->opval.val->type;
- TETYPE (tree) = getSpec (TTYPE (tree));
- tree->left = NULL;
- tree->right = NULL;
- return tree;
- }
+ 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 0
- 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;
- }
- #endif
- 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;
+ if (IS_LITERAL (RETYPE (tree)))
+ {
+ #if 0
+ 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->filename = tree->filename;
+ newTree->left->lineno = tree->lineno;
+ LTYPE (newTree) = sym->type;
+ LETYPE (newTree) = sym->etype;
+ LLVAL (newTree) = 1;
+ LRVAL (newTree) = 0;
+ TLVAL (newTree) = 1;
+ return newTree;
+ }
+ #endif
+ 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;
+ }
+ }
+ if (IS_GENPTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) && !IS_GENPTR (RTYPE (tree)) && (resultType != RESULT_TYPE_GPTR))
+ {
+ DCL_TYPE (LTYPE (tree)) = DCL_TYPE (RTYPE (tree));
}
- }
TTYPE (tree) = LTYPE (tree);
LRVAL (tree) = 1;
/*----------------------------*/
case AND_OP:
case OR_OP:
- /* each must me arithmetic type or be a pointer */
+ /* each must be arithmetic type or be a pointer */
if (!IS_PTR (LTYPE (tree)) &&
- !IS_ARRAY (LTYPE (tree)) &&
- !IS_INTEGRAL (LTYPE (tree)))
- {
- werror (E_COMPARE_OP);
- goto errorTreeReturn;
- }
+ !IS_ARRAY (LTYPE (tree)) &&
+ !IS_INTEGRAL (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
+ goto errorTreeReturn;
+ }
if (!IS_PTR (RTYPE (tree)) &&
- !IS_ARRAY (RTYPE (tree)) &&
- !IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_COMPARE_OP);
- goto errorTreeReturn;
- }
+ !IS_ARRAY (RTYPE (tree)) &&
+ !IS_INTEGRAL (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
+ goto errorTreeReturn;
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) &&
- IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
- valFromType (RTYPE (tree)),
- tree->opval.op);
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ IS_LITERAL (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+ valFromType (RTYPE (tree)),
+ tree->opval.op);
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ return tree;
+ }
LRVAL (tree) = RRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
return tree;
/*------------------------------------------------------------------*/
case EQ_OP:
case NE_OP:
{
- ast *lt = optimizeCompare (tree);
+ ast *lt = optimizeCompare (tree);
- if (tree != lt)
- return lt;
+ if (tree != lt)
+ return lt;
}
/* if they are pointers they must be castable */
if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
- {
- 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;
- tree->left=tree->right;
- tree->right=s;
- }
- if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
- {
- werror (E_COMPARE_OP);
- fprintf (stderr, "comparing type ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, "to type ");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
- }
+ {
+ 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;
+ tree->left=tree->right;
+ tree->right=s;
+ }
+ if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+ {
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
+ fprintf (stderr, "comparing type ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, "to type ");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
+ }
/* else they should be promotable to one another */
else
- {
- if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
- (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
-
- if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
- {
- werror (E_COMPARE_OP);
- fprintf (stderr, "comparing type ");
- printTypeChain (LTYPE (tree), stderr);
- fprintf (stderr, "to type ");
- printTypeChain (RTYPE (tree), stderr);
- fprintf (stderr, "\n");
- goto errorTreeReturn;
- }
- }
- /* if unsigned value < 0 then always false */
+ {
+ if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
+ (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
+
+ if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+ {
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
+ fprintf (stderr, "comparing type ");
+ printTypeChain (LTYPE (tree), stderr);
+ fprintf (stderr, "to type ");
+ printTypeChain (RTYPE (tree), stderr);
+ fprintf (stderr, "\n");
+ goto errorTreeReturn;
+ }
+ }
+
+ {
+ CCR_RESULT ccr_result = CCR_OK;
+
+ /* if left is integral and right is literal
+ then check constant range */
+ if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
+ ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
+ tree->opval.op, FALSE);
+ if (ccr_result == CCR_OK &&
+ IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
+ ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
+ tree->opval.op, TRUE);
+ switch (ccr_result)
+ {
+ case CCR_ALWAYS_TRUE:
+ case CCR_ALWAYS_FALSE:
+ if (!options.lessPedantic)
+ werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
+ ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
+ return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), 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 the parent is an ifx, then we could do */
- /* return tree->left; */
- 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_CHECK);
- }
+ ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
+ {
+ if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
+ {
+ /* the parent is an ifx: */
+ /* if (unsigned value) */
+ return tree->left;
+ }
+
+ /* (unsigned value) ? 1 : 0 */
+ tree->opval.op = '?';
+ tree->right = newNode (':',
+ newAst_VALUE (constCharVal (1)),
+ tree->right); /* val 0 */
+ tree->right->filename = tree->filename;
+ tree->right->lineno = tree->lineno;
+ tree->right->left->filename = tree->filename;
+ 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 || resultType == RESULT_TYPE_BIT))
+ {
+ 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)) &&
- IS_LITERAL (LTYPE (tree)))
- {
- tree->type = EX_VALUE;
- tree->opval.val = valCompare (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
- tree->opval.op);
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- return tree;
- }
+ IS_LITERAL (LTYPE (tree)))
+ {
+ tree->type = EX_VALUE;
+ tree->opval.val = valCompare (valFromType (LETYPE (tree)),
+ valFromType (RETYPE (tree)),
+ tree->opval.op);
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (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)) &&
+ (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
+ {
+ /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
+ if it's possible to use a 'signed char' */
+
+ /* is left a 'unsigned char'? */
+ if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
+ /* the value range of a 'unsigned char' is 0...255;
+ if the actual value is < 128 it can be changed to signed */
+ (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
+ {
+ /* now we've got 2 'signed char'! */
+ SPEC_USIGN (RETYPE (tree)) = 0;
+ }
+ /* same test for the left operand: */
+ else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
+ (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
+ {
+ SPEC_USIGN (LETYPE (tree)) = 0;
+ }
+ else
+ {
+ werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
+ tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
+ tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+
+ /* 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->filename = tree->left->filename;
+ tree->lineno = tree->left->lineno;
+ return decorateType (tree, resultType);
+ }
+ }
+
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* sizeof */
/*----------------------------*/
- case SIZEOF: /* evaluate wihout code generation */
+ case SIZEOF: /* evaluate wihout code generation */
/* change the type to a integer */
+ {
+ int size = getSize (tree->right->ftype);
+
+ SNPRINTF(buffer, sizeof(buffer), "%d", size);
+ if (!size && !IS_VOID(tree->right->ftype))
+ werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
+ }
tree->type = EX_VALUE;
- SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
tree->opval.val = constVal (buffer);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
+ tree->opval.val->type);
+
return tree;
/*------------------------------------------------------------------*/
/* typeof */
/*----------------------------*/
case TYPEOF:
- /* return typeof enum value */
- tree->type = EX_VALUE;
- {
- int typeofv = 0;
- if (IS_SPEC(tree->right->ftype)) {
- switch (SPEC_NOUN(tree->right->ftype)) {
- case V_INT:
- if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
- else typeofv = TYPEOF_INT;
- break;
- case V_FLOAT:
- typeofv = TYPEOF_FLOAT;
- break;
- case V_CHAR:
- typeofv = TYPEOF_CHAR;
- break;
- case V_VOID:
- typeofv = TYPEOF_VOID;
- break;
- case V_STRUCT:
- typeofv = TYPEOF_STRUCT;
- break;
- case V_BITFIELD:
- typeofv = TYPEOF_BITFIELD;
- break;
- case V_BIT:
- typeofv = TYPEOF_BIT;
- break;
- case V_SBIT:
- typeofv = TYPEOF_SBIT;
- break;
- default:
- break;
- }
- } else {
- switch (DCL_TYPE(tree->right->ftype)) {
- case POINTER:
- typeofv = TYPEOF_POINTER;
- break;
- case FPOINTER:
- typeofv = TYPEOF_FPOINTER;
- break;
- case CPOINTER:
- typeofv = TYPEOF_CPOINTER;
- break;
- case GPOINTER:
- typeofv = TYPEOF_GPOINTER;
- break;
- case PPOINTER:
- typeofv = TYPEOF_PPOINTER;
- break;
- case IPOINTER:
- typeofv = TYPEOF_IPOINTER;
- break;
- case ARRAY:
- typeofv = TYPEOF_ARRAY;
- break;
- case FUNCTION:
- typeofv = TYPEOF_FUNCTION;
- break;
- default:
- break;
- }
- }
- SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
- tree->opval.val = constVal (buffer);
- tree->right = tree->left = NULL;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- tree->opval.val->type);
- }
- return tree;
+ /* return typeof enum value */
+ tree->type = EX_VALUE;
+ {
+ int typeofv = 0;
+ if (IS_SPEC(tree->right->ftype)) {
+ switch (SPEC_NOUN(tree->right->ftype)) {
+ case V_INT:
+ if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
+ else typeofv = TYPEOF_INT;
+ break;
+ case V_FLOAT:
+ typeofv = TYPEOF_FLOAT;
+ break;
+ case V_FIXED16X16:
+ typeofv = TYPEOF_FIXED16X16;
+ break;
+ case V_CHAR:
+ typeofv = TYPEOF_CHAR;
+ break;
+ case V_VOID:
+ typeofv = TYPEOF_VOID;
+ break;
+ case V_STRUCT:
+ typeofv = TYPEOF_STRUCT;
+ break;
+ case V_BITFIELD:
+ typeofv = TYPEOF_BITFIELD;
+ break;
+ case V_BIT:
+ typeofv = TYPEOF_BIT;
+ break;
+ case V_SBIT:
+ typeofv = TYPEOF_SBIT;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (DCL_TYPE(tree->right->ftype)) {
+ case POINTER:
+ typeofv = TYPEOF_POINTER;
+ break;
+ case FPOINTER:
+ typeofv = TYPEOF_FPOINTER;
+ break;
+ case CPOINTER:
+ typeofv = TYPEOF_CPOINTER;
+ break;
+ case GPOINTER:
+ typeofv = TYPEOF_GPOINTER;
+ break;
+ case PPOINTER:
+ typeofv = TYPEOF_PPOINTER;
+ break;
+ case IPOINTER:
+ typeofv = TYPEOF_IPOINTER;
+ break;
+ case ARRAY:
+ typeofv = TYPEOF_ARRAY;
+ break;
+ case FUNCTION:
+ typeofv = TYPEOF_FUNCTION;
+ break;
+ default:
+ break;
+ }
+ }
+ SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
+ tree->opval.val = constVal (buffer);
+ tree->right = tree->left = NULL;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ tree->opval.val->type);
+ }
+ return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* conditional operator '?' */
case '?':
/* the type is value of the colon operator (on the right) */
assert (IS_COLON_OP (tree->right));
- /* if already known then replace the tree : optimizer will do it
- but faster to do it here */
+
+ /* If already known then replace the tree : optimizer will do it
+ but faster to do it here. If done before decorating tree->right
+ this can save generating unused const strings. */
if (IS_LITERAL (LTYPE (tree)))
- {
- if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
+ {
+ if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
return decorateType (tree->right->left, resultTypeProp);
- else
- return decorateType (tree->right->right, resultTypeProp);
- }
- else
- {
- tree->right = decorateType (tree->right, resultTypeProp);
- TTYPE (tree) = RTYPE (tree);
- TETYPE (tree) = getSpec (TTYPE (tree));
- }
- return tree;
+ else
+ return decorateType (tree->right->right, resultTypeProp);
+ }
- case ':':
- /* if they don't match we have a problem */
- if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
- {
- werror (E_TYPE_MISMATCH, "conditional operator", " ");
- goto errorTreeReturn;
- }
+ tree->right = decorateType (tree->right, resultTypeProp);
- TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
- TETYPE (tree) = getSpec (TTYPE (tree));
- return tree;
+ if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
+ ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
+ {
+ double valTrue = AST_FLOAT_VALUE (tree->right->left);
+ double valFalse = AST_FLOAT_VALUE (tree->right->right);
+
+ if ((valTrue != 0) && (valFalse == 0))
+ {
+ /* assign cond to result */
+ tree->left->decorated = 0;
+ return decorateType (tree->left, resultTypeProp);
+ }
+ else if ((valTrue == 0) && (valFalse != 0))
+ {
+ /* assign !cond to result */
+ tree->opval.op = '!';
+ tree->decorated = 0;
+ tree->right = NULL;
+ return decorateType (tree, resultTypeProp);
+ }
+ else
+ {
+ /* they have the same boolean value, make them equal */
+ tree->right->left = tree->right->right;
+ }
+ }
+
+ /* if they are equal then replace the tree */
+ if (isAstEqual (tree->right->left, tree->right->right))
+ {
+ return tree->right->left;
+ }
+
+ TTYPE (tree) = RTYPE (tree);
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ return tree;
+
+ case ':':
+ /* if they don't match we have a problem */
+ if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
+ (compareType (RTYPE (tree), LTYPE (tree)) == 0))
+ {
+ werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
+ goto errorTreeReturn;
+ }
+
+ TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+ resultType, tree->opval.op);
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ return tree;
#if 0 // assignment operators are converted by the parser
case DIV_ASSIGN:
/* for these it must be both must be integral */
if (!IS_ARITHMETIC (LTYPE (tree)) ||
- !IS_ARITHMETIC (RTYPE (tree)))
- {
- werror (E_OPS_INTEGRAL);
- goto errorTreeReturn;
- }
+ !IS_ARITHMETIC (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
+ goto errorTreeReturn;
+ }
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
- werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ goto errorTreeReturn;
+ }
LLVAL (tree) = 1;
return tree;
case LEFT_ASSIGN:
/* for these it must be both must be integral */
if (!IS_INTEGRAL (LTYPE (tree)) ||
- !IS_INTEGRAL (RTYPE (tree)))
- {
- werror (E_OPS_INTEGRAL);
- goto errorTreeReturn;
- }
+ !IS_INTEGRAL (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
+ goto errorTreeReturn;
+ }
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
+ goto errorTreeReturn;
+ }
LLVAL (tree) = 1;
return tree;
/*----------------------------*/
case SUB_ASSIGN:
if (!(IS_PTR (LTYPE (tree)) ||
- IS_ARITHMETIC (LTYPE (tree))))
- {
- werror (E_PLUS_INVALID, "-=");
- goto errorTreeReturn;
- }
+ IS_ARITHMETIC (LTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
+ goto errorTreeReturn;
+ }
if (!(IS_PTR (RTYPE (tree)) ||
- IS_ARITHMETIC (RTYPE (tree))))
- {
- werror (E_PLUS_INVALID, "-=");
- goto errorTreeReturn;
- }
+ IS_ARITHMETIC (RTYPE (tree))))
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
+ goto errorTreeReturn;
+ }
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, "-=");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "-=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
+ goto errorTreeReturn;
+ }
LLVAL (tree) = 1;
return tree;
/* this is not a unary operation */
/* if both pointers then problem */
if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
- {
- werror (E_PTR_PLUS_PTR);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
+ goto errorTreeReturn;
+ }
if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
- {
- werror (E_PLUS_INVALID, "+=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
+ goto errorTreeReturn;
+ }
if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
- {
- werror (E_PLUS_INVALID, "+=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
+ goto errorTreeReturn;
+ }
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, "+=");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "+=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
+ goto errorTreeReturn;
+ }
- tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
+ tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
tree->opval.op = '=';
return tree;
case '=':
/* cannot be an aggregate */
if (IS_AGGREGATE (LTYPE (tree)))
- {
- werror (E_AGGR_ASSIGN);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
+ goto errorTreeReturn;
+ }
/* they should either match or be castable */
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
- {
- werror (E_TYPE_MISMATCH, "assignment", " ");
- printFromToType(RTYPE(tree),LTYPE(tree));
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
+ printFromToType(RTYPE(tree),LTYPE(tree));
+ }
/* if the left side of the tree is of type void
then report error */
if (IS_VOID (LTYPE (tree)))
- {
- werror (E_CAST_ZERO);
- printFromToType(RTYPE(tree), LTYPE(tree));
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
+ printFromToType(RTYPE(tree), LTYPE(tree));
+ }
- TETYPE (tree) = getSpec (TTYPE (tree) =
- LTYPE (tree));
+ TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
RRVAL (tree) = 1;
LLVAL (tree) = 1;
if (!tree->initMode ) {
if (IS_CONSTANT(LTYPE(tree)))
- werror (E_CODE_WRITE, "=");
+ werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
}
if (LRVAL (tree))
- {
- werror (E_LVALUE_REQUIRED, "=");
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
+ goto errorTreeReturn;
+ }
return tree;
/* function call */
/*----------------------------*/
case CALL:
- parmNumber = 1;
- if (processParms (tree->left,
- FUNC_ARGS(tree->left->ftype),
- tree->right, &parmNumber, TRUE)) {
- goto errorTreeReturn;
- }
+ /* undo any explicit pointer derefernce; PCALL will handle it instead */
+ if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
+ {
+ if (tree->left->opval.op == '*' && !tree->left->right)
+ tree->left = tree->left->left;
+ }
- if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) &&
- !IFFUNC_ISBUILTIN(LTYPE(tree)))
- {
- reverseParms (tree->right);
- }
+ /* require a function or pointer to function */
+ if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+ goto errorTreeReturn;
+ }
- if (IS_CODEPTR(LTYPE(tree))) {
- TTYPE(tree) = LTYPE(tree)->next->next;
- } else {
- TTYPE(tree) = LTYPE(tree)->next;
- }
- TETYPE (tree) = getSpec (TTYPE (tree));
+ /* if there are parms, make sure that
+ parms are decorate / process / reverse only once */
+ if (!tree->right ||
+ !tree->right->decorated)
+ {
+ sym_link *functype;
+ parmNumber = 1;
+
+ if (IS_FUNCPTR (LTYPE (tree)))
+ {
+ functype = LTYPE (tree)->next;
+ processFuncPtrArgs (functype);
+ }
+ else
+ functype = LTYPE (tree);
+
+ if (processParms (tree->left, FUNC_ARGS(functype),
+ &tree->right, &parmNumber, TRUE))
+ {
+ goto errorTreeReturn;
+ }
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+ !IFFUNC_ISBUILTIN(functype))
+ {
+ reverseParms (tree->right);
+ }
+
+ TTYPE (tree) = functype->next;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ }
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
case RETURN:
if (!tree->right)
- goto voidcheck;
+ goto voidcheck;
if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
- {
- werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
- printFromToType (RTYPE(tree), currFunc->type->next);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
+ printFromToType (RTYPE(tree), currFunc->type->next);
+ goto errorTreeReturn;
+ }
if (IS_VOID (currFunc->type->next)
- && tree->right &&
- !IS_VOID (RTYPE (tree)))
- {
- werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
- goto errorTreeReturn;
- }
+ && tree->right &&
+ !IS_VOID (RTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
+ goto errorTreeReturn;
+ }
/* if there is going to be a casting required then add it */
if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
- {
- tree->right =
- decorateType (newNode (CAST,
- newAst_LINK (copyLinkChain (currFunc->type->next)),
- tree->right),
- RESULT_CHECK);
- }
+ {
+ tree->right =
+ decorateType (newNode (CAST,
+ newAst_LINK (copyLinkChain (currFunc->type->next)),
+ tree->right),
+ IS_GENPTR (currFunc->type->next) ? RESULT_TYPE_GPTR : RESULT_TYPE_NONE);
+ }
RRVAL (tree) = 1;
return tree;
voidcheck:
if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
- {
- werror (W_VOID_FUNC, currFunc->name);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
+ goto errorTreeReturn;
+ }
TTYPE (tree) = TETYPE (tree) = NULL;
return tree;
case SWITCH:
/* the switch value must be an integer */
if (!IS_INTEGRAL (LTYPE (tree)))
- {
- werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
- goto errorTreeReturn;
- }
+ {
+ werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
+ goto errorTreeReturn;
+ }
LRVAL (tree) = 1;
TTYPE (tree) = TETYPE (tree) = NULL;
return tree;
/*----------------------------*/
case IFX:
tree->left = backPatchLabels (tree->left,
- tree->trueLabel,
- tree->falseLabel);
+ tree->trueLabel,
+ tree->falseLabel);
TTYPE (tree) = TETYPE (tree) = NULL;
return tree;
/*----------------------------*/
case FOR:
- decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
- decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
- decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
+ 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
do */
{
- symbol *sym;
- ast *init, *end;
-
- if (isLoopReversible (tree, &sym, &init, &end))
- return reverseLoop (tree, sym, init, end);
- else
- return decorateType (createFor (AST_FOR (tree, trueLabel),
- AST_FOR (tree, continueLabel),
- AST_FOR (tree, falseLabel),
- AST_FOR (tree, condLabel),
- AST_FOR (tree, initExpr),
- AST_FOR (tree, condExpr),
- AST_FOR (tree, loopExpr),
- tree->left), RESULT_CHECK);
+ symbol *sym;
+ ast *init, *end;
+
+ if (isLoopReversible (tree, &sym, &init, &end))
+ return reverseLoop (tree, sym, init, end);
+ else
+ return decorateType (createFor (AST_FOR (tree, trueLabel),
+ AST_FOR (tree, continueLabel),
+ AST_FOR (tree, falseLabel),
+ AST_FOR (tree, condLabel),
+ AST_FOR (tree, initExpr),
+ AST_FOR (tree, condExpr),
+ AST_FOR (tree, loopExpr),
+ tree->left), RESULT_TYPE_NONE);
}
+ case PARAM:
+ werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "node PARAM shouldn't be processed here");
+ /* but in processParams() */
+ return tree;
default:
TTYPE (tree) = TETYPE (tree) = NULL;
return tree;
sizeofOp (sym_link * type)
{
char buff[10];
+ int size;
/* make sure the type is complete and sane */
checkTypeSanity(type, "(sizeof)");
/* get the size and convert it to character */
- SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
+ SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
+ if (!size && !IS_VOID(type))
+ werror (E_SIZEOF_INCOMPLETE_TYPE);
/* now convert into value */
return constVal (buff);
/*-----------------------------------------------------------------*/
/* 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;
/* if left is already a IFX then just change the if true label in that */
if (!IS_IFX (tree->left))
- tree->left = newIfxNode (tree->left, localLabel, falseLabel);
+ tree->left = newIfxNode (tree->left, localLabel, falseLabel);
tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
/* right is a IFX then just join */
if (IS_IFX (tree->right))
- return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
+ return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
tree->right = createLabel (localLabel, tree->right);
tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
/* if left is already a IFX then just change the if true label in that */
if (!IS_IFX (tree->left))
- tree->left = newIfxNode (tree->left, trueLabel, localLabel);
+ tree->left = newIfxNode (tree->left, trueLabel, localLabel);
tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
/* right is a IFX then just join */
if (IS_IFX (tree->right))
- return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
+ return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
tree->right = createLabel (localLabel, tree->right);
tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
/* change not */
if (IS_NOT (tree))
{
- int wasnot = IS_NOT (tree->left);
+ /* call with exchanged labels */
tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
- /* if the left is already a IFX */
+ /* if left isn't already a IFX */
if (!IS_IFX (tree->left))
- tree->left = newNode (IFX, tree->left, NULL);
-
- if (wasnot)
- {
- tree->left->trueLabel = trueLabel;
- tree->left->falseLabel = falseLabel;
- }
- else
- {
- tree->left->trueLabel = falseLabel;
- tree->left->falseLabel = trueLabel;
- }
+ {
+ 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->right = ex->right;
+
ex->level++;
+ ex->filename = NULL;
ex->lineno = 0;
return ex;
}
else
addSym (LabelTab, label, name, label->level, 0, 0);
+ label->isitmp = 1;
label->islbl = 1;
label->key = labelKey++;
rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
+ rValue->filename = NULL;
rValue->lineno = 0;
return rValue;
return NULL;
}
- caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
+ caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
/* if not a constant then error */
if (!IS_LITERAL (caseVal->ftype))
{
{
/* also order the cases according to value */
value *pval = NULL;
- int cVal = (int) floatFromVal (caseVal->opval.val);
- while (val && (int) floatFromVal (val) < cVal)
- {
- pval = val;
- val = val->next;
- }
+ int cVal = (int) ulFromVal (caseVal->opval.val);
+ while (val && (int) ulFromVal (val) < cVal)
+ {
+ pval = val;
+ val = val->next;
+ }
/* if we reached the end then */
if (!val)
- {
- pval->next = caseVal->opval.val;
- }
- else if ((int) floatFromVal (val) == cVal)
- {
- werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
- "case");
- return NULL;
- }
+ {
+ pval->next = caseVal->opval.val;
+ }
+ else if ((int) ulFromVal (val) == cVal)
+ {
+ werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
+ "case");
+ return NULL;
+ }
else
- {
- /* we found a value greater than */
- /* the current value we must add this */
- /* before the value */
- caseVal->opval.val->next = val;
-
- /* if this was the first in chain */
- if (swStat->values.switchVals.swVals == val)
- swStat->values.switchVals.swVals =
- caseVal->opval.val;
- else
- pval->next = caseVal->opval.val;
- }
+ {
+ /* we found a value greater than */
+ /* the current value we must add this */
+ /* before the value */
+ caseVal->opval.val->next = val;
+
+ /* if this was the first in chain */
+ if (swStat->values.switchVals.swVals == val)
+ swStat->values.switchVals.swVals =
+ caseVal->opval.val;
+ else
+ pval->next = caseVal->opval.val;
+ }
}
/* create the case label */
- SNPRINTF(caseLbl, sizeof(caseLbl),
- "_case_%d_%d",
- swStat->values.switchVals.swNum,
- (int) floatFromVal (caseVal->opval.val));
+ SNPRINTF(caseLbl, sizeof(caseLbl),
+ "_case_%d_%d",
+ swStat->values.switchVals.swNum,
+ (int) ulFromVal (caseVal->opval.val));
rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
+ rexpr->filename = 0;
rexpr->lineno = 0;
return rexpr;
}
if (swStat->values.switchVals.swDefault)
{
werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
- "default");
+ "default");
return NULL;
}
/* create the label */
SNPRINTF (defLbl, sizeof(defLbl),
- "_default_%d", swStat->values.switchVals.swNum);
+ "_default_%d", swStat->values.switchVals.swNum);
return createLabel (newSymbol (defLbl, 0), stmnt);
}
if (elseBody)
{
ifBody = newNode (NULLOP, ifBody,
- newNode (GOTO,
- newAst_VALUE (symbolVal (ifEnd)),
- NULL));
+ newNode (GOTO,
+ newAst_VALUE (symbolVal (ifEnd)),
+ NULL));
/* put the elseLabel on the else body */
elseBody = createLabel (ifFalse, elseBody);
/* out the end at the end of the body */
elseBody = newNode (NULLOP,
- elseBody,
- createLabel (ifEnd, NULL));
+ elseBody,
+ createLabel (ifEnd, NULL));
}
else
{
ifBody = newNode (NULLOP, ifBody,
- createLabel (ifFalse, NULL));
+ createLabel (ifFalse, NULL));
}
condAst = backPatchLabels (condAst, ifTrue, ifFalse);
if (IS_IFX (condAst))
ifTree = newIfxNode (condAst, ifTrue, ifFalse);
return newNode (NULLOP, ifTree,
- newNode (NULLOP, ifBody, elseBody));
+ newNode (NULLOP, ifBody, elseBody));
}
/*-----------------------------------------------------------------*/
ast *
createDo (symbol * trueLabel, symbol * continueLabel,
- symbol * falseLabel, ast * condAst, ast * doBody)
+ symbol * falseLabel, ast * condAst, ast * doBody)
{
ast *doTree;
/* if the body does not exist then it is simple */
if (!doBody)
{
- condAst = backPatchLabels (condAst, continueLabel, NULL);
+ condAst = backPatchLabels (condAst, continueLabel, falseLabel);
doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
- : newNode (IFX, createLabel (continueLabel, condAst), NULL));
+ : newNode (IFX, createLabel (continueLabel, condAst), NULL));
doTree->trueLabel = continueLabel;
doTree->falseLabel = NULL;
+
+ doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
return doTree;
}
doBody = createLabel (trueLabel, doBody);
/* attach the continue label to end of body */
doBody = newNode (NULLOP, doBody,
- createLabel (continueLabel, NULL));
+ createLabel (continueLabel, NULL));
/* now put the break label at the end */
if (IS_IFX (condAst))
/*-----------------------------------------------------------------*/
ast *
createFor (symbol * trueLabel, symbol * continueLabel,
- symbol * falseLabel, symbol * condLabel,
- ast * initExpr, ast * condExpr, ast * loopExpr,
- ast * forBody)
+ symbol * falseLabel, symbol * condLabel,
+ ast * initExpr, ast * condExpr, ast * loopExpr,
+ ast * forBody)
{
ast *forTree;
/* the same way as a while */
if (!loopExpr)
return newNode (NULLOP, initExpr,
- createWhile (trueLabel, continueLabel,
- falseLabel, condExpr, forBody));
+ createWhile (trueLabel, continueLabel,
+ falseLabel, condExpr, forBody));
/* vanilla for statement */
condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
/* attach continue to forLoop expression & attach */
/* goto the forcond @ and of loopExpression */
loopExpr = createLabel (continueLabel,
- newNode (NULLOP,
- loopExpr,
- newNode (GOTO,
- newAst_VALUE (symbolVal (condLabel)),
- NULL)));
+ newNode (NULLOP,
+ loopExpr,
+ newNode (GOTO,
+ newAst_VALUE (symbolVal (condLabel)),
+ NULL)));
/* now start putting them together */
forTree = newNode (NULLOP, initExpr, condExpr);
forTree = newNode (NULLOP, forTree, forBody);
forTree = newNode (NULLOP, forTree, loopExpr);
/* finally add the break label */
forTree = newNode (NULLOP, forTree,
- createLabel (falseLabel, NULL));
+ createLabel (falseLabel, NULL));
return forTree;
}
/*-----------------------------------------------------------------*/
ast *
createWhile (symbol * trueLabel, symbol * continueLabel,
- symbol * falseLabel, ast * condExpr, ast * whileBody)
+ symbol * falseLabel, ast * condExpr, ast * whileBody)
{
ast *whileTree;
/* put the continue label */
condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
condExpr = createLabel (continueLabel, condExpr);
+ condExpr->filename = NULL;
condExpr->lineno = 0;
/* put the body label in front of the body */
whileBody = createLabel (trueLabel, whileBody);
+ whileBody->filename = NULL;
whileBody->lineno = 0;
/* put a jump to continue at the end of the body */
/* and put break label at the end of the body */
whileBody = newNode (NULLOP,
- whileBody,
- newNode (GOTO,
- newAst_VALUE (symbolVal (continueLabel)),
- createLabel (falseLabel, NULL)));
+ whileBody,
+ newNode (GOTO,
+ newAst_VALUE (symbolVal (continueLabel)),
+ createLabel (falseLabel, NULL)));
/* put it all together */
if (IS_IFX (condExpr))
}
/*-----------------------------------------------------------------*/
-/* optimizeGetHbit - get highest order bit of the expression */
+/* isShiftRightLitVal _BitAndLitVal - helper function */
/*-----------------------------------------------------------------*/
-ast *
-optimizeGetHbit (ast * tree)
+static ast *
+isShiftRightLitVal_BitAndLitVal (ast * tree)
{
- int i, j;
/* if this is not a bit and */
if (!IS_BITAND (tree))
- return tree;
+ return NULL;
/* will look for tree of the form
- ( expr >> ((sizeof expr) -1) ) & 1 */
+ ( expr >> litval2) & litval1 */
if (!IS_AST_LIT_VALUE (tree->right))
+ return NULL;
+
+ if (!IS_RIGHT_OP (tree->left))
+ return NULL;
+
+ if (!IS_AST_LIT_VALUE (tree->left->right))
+ return NULL;
+
+ return tree->left->left;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitAndPowOf2 - helper function */
+/*-----------------------------------------------------------------*/
+static int
+isBitAndPow2 (ast * tree)
+{
+ /* if this is not a bit and */
+ if (!IS_BITAND (tree))
+ return -1;
+
+ /* will look for tree of the form
+ ( expr & (1 << litval) */
+ if (!IS_AST_LIT_VALUE (tree->right))
+ return -1;
+
+ return powof2 (AST_ULONG_VALUE (tree->right));
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetHbit - get highest order bit of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
+{
+ unsigned int i, j;
+ ast * expr;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ if ((AST_ULONG_VALUE (tree->right) != 1) ||
+ ((i = AST_ULONG_VALUE (tree->left->right)) !=
+ (j = (getSize (TTYPE (expr)) * 8 - 1))))
+ expr = NULL;
+ }
+ if (!expr && (resultType == RESULT_TYPE_BIT))
+ {
+ expr = tree->left;
+ if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
+ expr = NULL;
+ }
+ if (!expr)
return tree;
- if (AST_LIT_VALUE (tree->right) != 1)
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
return tree;
- if (!IS_RIGHT_OP (tree->left))
+ return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetAbit - get a single bit of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
+{
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ if (AST_ULONG_VALUE (tree->right) != 1)
+ expr = NULL;
+ count = tree->left->right;
+ }
+ if (!expr && (resultType == RESULT_TYPE_BIT))
+ {
+ int p2 = isBitAndPow2 (tree);
+ if (p2 >= 0)
+ {
+ expr = tree->left;
+ count = newAst_VALUE (valueFromLit (p2));
+ }
+ }
+ if (!expr)
return tree;
- if (!IS_AST_LIT_VALUE (tree->left->right))
+ /* make sure the port supports GETABIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
return tree;
- if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
- (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
+ return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetByte - get a byte of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetByte (ast * tree, RESULT_TYPE resultType)
+{
+ unsigned int i = 0;
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ i = AST_ULONG_VALUE (tree->left->right);
+ count = tree->left->right;
+ if (AST_ULONG_VALUE (tree->right) != 0xFF)
+ expr = NULL;
+ }
+ if (!expr && resultType == RESULT_TYPE_CHAR)
+ {
+ /* if this is a right shift over a multiple of 8 */
+ if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+ {
+ i = AST_ULONG_VALUE (tree->right);
+ count = tree->right;
+ expr = tree->left;
+ }
+ }
+ if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
return tree;
-
- /* make sure the port supports GETHBIT */
+
+ /* make sure the port supports GETBYTE */
if (port->hasExtBitOp
- && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+ && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
+ return tree;
+
+ return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetWord - get two bytes of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetWord (ast * tree, RESULT_TYPE resultType)
+{
+ unsigned int i = 0;
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ i = AST_ULONG_VALUE (tree->left->right);
+ count = tree->left->right;
+ if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
+ expr = NULL;
+ }
+ if (!expr && resultType == RESULT_TYPE_INT)
+ {
+ /* if this is a right shift over a multiple of 8 */
+ if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+ {
+ i = AST_ULONG_VALUE (tree->right);
+ count = tree->right;
+ expr = tree->left;
+ }
+ }
+ if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
return tree;
- return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
+ /* make sure the port supports GETWORD */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
+ return tree;
+ return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
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) &&
{
if (!SPEC_USIGN (TETYPE (root->left->left)))
- return root;
+ return root;
if (!IS_AST_LIT_VALUE (root->left->right) ||
- !IS_AST_LIT_VALUE (root->right->right))
- goto tryNext0;
+ !IS_AST_LIT_VALUE (root->right->right))
+ goto tryNext0;
/* make sure it is the same expression */
if (!isAstEqual (root->left->left,
- root->right->left))
- goto tryNext0;
+ root->right->left))
+ goto tryNext0;
- if (AST_LIT_VALUE (root->left->right) != 1)
- goto tryNext0;
+ if (AST_ULONG_VALUE (root->left->right) != 1)
+ goto tryNext0;
- if (AST_LIT_VALUE (root->right->right) !=
- (getSize (TTYPE (root->left->left)) * 8 - 1))
- goto tryNext0;
+ if (AST_ULONG_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 8 - 1))
+ goto tryNext0;
/* make sure the port supports RLC */
if (port->hasExtBitOp
{
if (!SPEC_USIGN (TETYPE (root->left->left)))
- return root;
+ return root;
if (!IS_AST_LIT_VALUE (root->left->right) ||
- !IS_AST_LIT_VALUE (root->right->right))
- goto tryNext1;
+ !IS_AST_LIT_VALUE (root->right->right))
+ goto tryNext1;
/* make sure it is the same symbol */
if (!isAstEqual (root->left->left,
- root->right->left))
- goto tryNext1;
+ root->right->left))
+ goto tryNext1;
- if (AST_LIT_VALUE (root->right->right) != 1)
- goto tryNext1;
+ if (AST_ULONG_VALUE (root->right->right) != 1)
+ goto tryNext1;
- if (AST_LIT_VALUE (root->left->right) !=
- (getSize (TTYPE (root->left->left)) * 8 - 1))
- goto tryNext1;
+ if (AST_ULONG_VALUE (root->left->right) !=
+ (getSize (TTYPE (root->left->left)) * 8 - 1))
+ goto tryNext1;
/* make sure the port supports RLC */
if (port->hasExtBitOp
{
if (!SPEC_USIGN (TETYPE (root->left->left)))
- return root;
+ return root;
if (!IS_AST_LIT_VALUE (root->left->right) ||
- !IS_AST_LIT_VALUE (root->right->right))
- goto tryNext2;
+ !IS_AST_LIT_VALUE (root->right->right))
+ goto tryNext2;
/* make sure it is the same symbol */
if (!isAstEqual (root->left->left,
- root->right->left))
- goto tryNext2;
+ root->right->left))
+ goto tryNext2;
- if (AST_LIT_VALUE (root->left->right) != 1)
- goto tryNext2;
+ if (AST_ULONG_VALUE (root->left->right) != 1)
+ goto tryNext2;
- if (AST_LIT_VALUE (root->right->right) !=
- (getSize (TTYPE (root->left->left)) * 8 - 1))
- goto tryNext2;
+ if (AST_ULONG_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 8 - 1))
+ goto tryNext2;
/* make sure the port supports RRC */
if (port->hasExtBitOp
{
if (!SPEC_USIGN (TETYPE (root->left->left)))
- return root;
+ return root;
if (!IS_AST_LIT_VALUE (root->left->right) ||
- !IS_AST_LIT_VALUE (root->right->right))
- return root;
+ !IS_AST_LIT_VALUE (root->right->right))
+ return root;
/* make sure it is the same symbol */
if (!isAstEqual (root->left->left,
- root->right->left))
- return root;
+ root->right->left))
+ return root;
- if (AST_LIT_VALUE (root->right->right) != 1)
- return root;
+ if (AST_ULONG_VALUE (root->right->right) != 1)
+ return root;
- if (AST_LIT_VALUE (root->left->right) !=
- (getSize (TTYPE (root->left->left)) * 8 - 1))
- return root;
+ if (AST_ULONG_VALUE (root->left->right) !=
+ (getSize (TTYPE (root->left->left)) * 8 - 1))
+ return root;
/* make sure the port supports RRC */
if (port->hasExtBitOp
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;
{
if (!SPEC_USIGN (TETYPE (root->left->left)))
- return root;
+ return root;
if (!IS_AST_LIT_VALUE (root->left->right) ||
- !IS_AST_LIT_VALUE (root->right->right))
- return root;
+ !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;
+ root->right->left))
+ return root;
- if (AST_LIT_VALUE (root->left->right) !=
- (getSize (TTYPE (root->left->left)) * 4))
- return root;
+ if (AST_ULONG_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;
+ if (AST_ULONG_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
/* make sure the port supports SWAP */
if (port->hasExtBitOp
}
/*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables */
+/* optimizeCompare - optimizes compares for bit variables */
/*-----------------------------------------------------------------*/
static ast *
optimizeCompare (ast * root)
if (isAstEqual (root->left, root->right))
{
switch (root->opval.op)
- {
- case '>':
- case '<':
- case NE_OP:
- optExpr = newAst_VALUE (constVal ("0"));
- break;
- case GE_OP:
- case LE_OP:
- case EQ_OP:
- optExpr = newAst_VALUE (constVal ("1"));
- break;
- }
-
- return decorateType (optExpr, RESULT_CHECK);
+ {
+ case '>':
+ case '<':
+ case NE_OP:
+ optExpr = newAst_VALUE (constCharVal (0));
+ break;
+ case GE_OP:
+ case LE_OP:
+ case EQ_OP:
+ optExpr = newAst_VALUE (constCharVal (1));
+ break;
+ }
+
+ return decorateType (optExpr, RESULT_TYPE_NONE);
}
vleft = (root->left->type == EX_VALUE ?
- root->left->opval.val : NULL);
+ root->left->opval.val : NULL);
vright = (root->right->type == EX_VALUE ?
- root->right->opval.val : NULL);
+ root->right->opval.val : NULL);
/* if left is a BITVAR in BITSPACE */
- /* and right is a LITERAL then opt- */
- /* imize else do nothing */
+ /* and right is a LITERAL then */
+ /* optimize else do nothing */
if (vleft && vright &&
IS_BITVAR (vleft->etype) &&
IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
{
/* if right side > 1 then comparison may never succeed */
- if ((litValue = (int) floatFromVal (vright)) > 1)
- {
- werror (W_BAD_COMPARE);
- goto noOptimize;
- }
+ if ((litValue = (int) ulFromVal (vright)) > 1)
+ {
+ werror (W_BAD_COMPARE);
+ goto noOptimize;
+ }
if (litValue)
- {
- switch (root->opval.op)
- {
- case '>': /* bit value greater than 1 cannot be */
- werror (W_BAD_COMPARE);
- goto noOptimize;
- break;
-
- case '<': /* bit value < 1 means 0 */
- case NE_OP:
- optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
- break;
-
- case LE_OP: /* bit value <= 1 means no check */
- optExpr = newAst_VALUE (vright);
- break;
-
- case GE_OP: /* bit value >= 1 means only check for = */
- case EQ_OP:
- optExpr = newAst_VALUE (vleft);
- break;
- }
- }
+ {
+ switch (root->opval.op)
+ {
+ case '>': /* bit value greater than 1 cannot be */
+ werror (W_BAD_COMPARE);
+ goto noOptimize;
+ break;
+
+ case '<': /* bit value < 1 means 0 */
+ case NE_OP:
+ optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
+ break;
+
+ case LE_OP: /* bit value <= 1 means no check */
+ optExpr = newAst_VALUE (vright);
+ break;
+
+ case GE_OP: /* bit value >= 1 means only check for = */
+ case EQ_OP:
+ optExpr = newAst_VALUE (vleft);
+ break;
+ }
+ }
else
- { /* literal is zero */
- switch (root->opval.op)
- {
- case '<': /* bit value < 0 cannot be */
- werror (W_BAD_COMPARE);
- goto noOptimize;
- break;
-
- case '>': /* bit value > 0 means 1 */
- case NE_OP:
- optExpr = newAst_VALUE (vleft);
- break;
-
- case LE_OP: /* bit value <= 0 means no check */
- case GE_OP: /* bit value >= 0 means no check */
- werror (W_BAD_COMPARE);
- goto noOptimize;
- break;
-
- case EQ_OP: /* bit == 0 means ! of bit */
- optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
- break;
- }
- }
- return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
- } /* end-of-if of BITVAR */
+ { /* literal is zero */
+ switch (root->opval.op)
+ {
+ case '<': /* bit value < 0 cannot be */
+ werror (W_BAD_COMPARE);
+ goto noOptimize;
+ break;
+
+ case '>': /* bit value > 0 means 1 */
+ case NE_OP:
+ optExpr = newAst_VALUE (vleft);
+ break;
+
+ case LE_OP: /* bit value <= 0 means no check */
+ case GE_OP: /* bit value >= 0 means no check */
+ werror (W_BAD_COMPARE);
+ goto noOptimize;
+ break;
+
+ case EQ_OP: /* bit == 0 means ! of bit */
+ optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
+ break;
+ }
+ }
+ return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
+ } /* end-of-if of BITVAR */
noOptimize:
return root;
}
+
/*-----------------------------------------------------------------*/
/* addSymToBlock : adds the symbol to the first block we find */
/*-----------------------------------------------------------------*/
-void
+void
addSymToBlock (symbol * sym, ast * tree)
{
/* reached end of tree or a leaf */
/*-----------------------------------------------------------------*/
/* processRegParms - do processing for register parameters */
/*-----------------------------------------------------------------*/
-static void
+static void
processRegParms (value * args, ast * body)
{
while (args)
{
if (IS_REGPARM (args->etype))
- addSymToBlock (args->sym, body);
+ addSymToBlock (args->sym, body);
args = args->next;
}
}
return 1;
}
+/*------------------------------------------------------------------*/
+/* fixupInlineLabel - change a label in an inlined function so that */
+/* it is always unique no matter how many times */
+/* the function is inlined. */
+/*------------------------------------------------------------------*/
+static void
+fixupInlineLabel (symbol * sym)
+{
+ char name[SDCC_NAME_MAX + 1];
+
+ SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
+ strcpy (sym->name, name);
+}
+
+/*------------------------------------------------------------------*/
+/* copyAstLoc - copy location information (file, line, block, etc.) */
+/* from one ast node to another */
+/*------------------------------------------------------------------*/
+static void
+copyAstLoc (ast * dest, ast * src)
+{
+ dest->filename = src->filename;
+ dest->lineno = src->lineno;
+ dest->level = src->level;
+ dest->block = src->block;
+ dest->seqPoint = src->seqPoint;
+}
+
+/*-----------------------------------------------------------------*/
+/* fixupInline - perform various fixups on an inline function tree */
+/* to take into account that it is no longer a */
+/* stand-alone function. */
+/*-----------------------------------------------------------------*/
+static void
+fixupInline (ast * tree, int level)
+{
+ int savedBlockno = currBlockno;
+
+ if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+ {
+ symbol * decls;
+
+ currBlockno = ++blockNo;
+ level++;
+
+ /* Add any declared variables back into the symbol table */
+ decls = tree->values.sym;
+ while (decls)
+ {
+ decls->level = level;
+ decls->block = currBlockno;
+ addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
+ decls = decls->next;
+ }
+ }
+
+ tree->level = level;
+ tree->block = currBlockno;
+
+ /* Update symbols */
+ if (IS_AST_VALUE (tree) &&
+ tree->opval.val->sym)
+ {
+ symbol * sym = tree->opval.val->sym;
+
+ sym->level = level;
+ sym->block = currBlockno;
+
+ sym->reqv = NULL;
+ SYM_SPIL_LOC (sym) = NULL;
+ sym->key = 0;
+
+ /* If the symbol is a label, we need to renumber it */
+ if (sym->islbl)
+ fixupInlineLabel (sym);
+ }
+
+ /* Update IFX target labels */
+ if (tree->type == EX_OP && tree->opval.op == IFX)
+ {
+ if (tree->trueLabel)
+ fixupInlineLabel (tree->trueLabel);
+ if (tree->falseLabel)
+ fixupInlineLabel (tree->falseLabel);
+ }
+
+ /* Replace RETURN with optional assignment and a GOTO to the end */
+ /* of the inlined function */
+ if (tree->type == EX_OP && tree->opval.op == RETURN)
+ {
+ ast * assignTree = NULL;
+ ast * gotoTree;
+
+ if (inlineState.retsym && tree->right)
+ {
+ assignTree = newNode ('=',
+ newAst_VALUE (symbolVal (inlineState.retsym)),
+ tree->right);
+ copyAstLoc (assignTree, tree);
+ }
+
+ gotoTree = newNode (GOTO,
+ newAst_VALUE (symbolVal (inlineState.retlab)),
+ NULL);
+ copyAstLoc (gotoTree, tree);
+
+ tree->opval.op = NULLOP;
+ tree->left = assignTree;
+ tree->right = gotoTree;
+ }
+
+ /* Update any children */
+ if (tree->left)
+ fixupInline (tree->left, level);
+ if (tree->right)
+ fixupInline (tree->right, level);
+
+ if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
+ {
+ symbol * label = tree->left->opval.val->sym;
+
+ label->key = labelKey++;
+ /* Add this label back into the symbol table */
+ addSym (LabelTab, label, label->name, label->level, 0, 0);
+ }
+
+ if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+ {
+ level--;
+ currBlockno = savedBlockno;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineAddDecl - add a variable declaration to an ast block. It */
+/* is also added to the symbol table if addSymTab */
+/* is nonzero. */
+/*-----------------------------------------------------------------*/
+static void
+inlineAddDecl (symbol * sym, ast * block, int addSymTab)
+{
+ sym->reqv = NULL;
+ SYM_SPIL_LOC (sym) = NULL;
+ sym->key = 0;
+ if (block != NULL)
+ {
+ symbol **decl = &(block->values.sym);
+
+ sym->level = block->level;
+ sym->block = block->block;
+
+ while (*decl)
+ {
+ if (strcmp ((*decl)->name, sym->name) == 0)
+ return;
+ decl = &( (*decl)->next );
+ }
+
+ *decl = sym;
+
+ if (addSymTab)
+ addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
+
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineTempVar - create a temporary variable for inlining */
+/*-----------------------------------------------------------------*/
+static symbol *
+inlineTempVar (sym_link * type, int level)
+{
+ symbol * sym;
+
+ sym = newSymbol (genSymName(level), level );
+ sym->type = copyLinkChain (type);
+ sym->etype = getSpec(sym->type);
+ SPEC_SCLS (sym->etype) = S_AUTO;
+ SPEC_OCLS (sym->etype) = NULL;
+ SPEC_EXTR (sym->etype) = 0;
+ SPEC_STAT (sym->etype) = 0;
+ if IS_SPEC (sym->type)
+ SPEC_VOLATILE (sym->type) = 0;
+ else
+ DCL_PTR_VOLATILE (sym->type) = 0;
+ SPEC_ABSA (sym->etype) = 0;
+
+ return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindParmRecurse - recursive function for inlineFindParm */
+/*-----------------------------------------------------------------*/
+static ast *
+inlineFindParmRecurse (ast * parms, int *index)
+{
+ if (!parms)
+ return NULL;
+
+ if (parms->type == EX_OP && parms->opval.op == PARAM)
+ {
+ ast * p;
+
+ p=inlineFindParmRecurse (parms->left, index);
+ if (p)
+ return p;
+ p=inlineFindParmRecurse (parms->right, index);
+ if (p)
+ return p;
+ }
+ if (!*index)
+ return parms;
+ (*index)--;
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindParm - search an ast tree of parameters to find one */
+/* at a particular index (0=first parameter). */
+/* Returns NULL if not found. */
+/*-----------------------------------------------------------------*/
+static ast *
+inlineFindParm (ast * parms, int index)
+{
+ return inlineFindParmRecurse (parms, &index);
+}
+
+/*-----------------------------------------------------------------*/
+/* expandInlineFuncs - replace calls to inline functions with the */
+/* function itself */
+/*-----------------------------------------------------------------*/
+static void
+expandInlineFuncs (ast * tree, ast * block)
+{
+ if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
+ && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
+ {
+ symbol * func = tree->left->opval.val->sym;
+ symbol * csym;
+
+ /* The symbol is probably not bound yet, so find the real one */
+ csym = findSymWithLevel (SymbolTab, func);
+ if (csym)
+ func = csym;
+
+ /* Is this an inline function that we can inline? */
+ if (IFFUNC_ISINLINE (func->type) && func->funcTree)
+ {
+ symbol * retsym = NULL;
+ symbol * retlab;
+ ast * inlinetree;
+ ast * inlinetree2;
+ ast * temptree;
+ value * args;
+ int argIndex;
+
+ /* Generate a label for the inlined function to branch to */
+ /* in case it contains a return statement */
+ retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
+ retlab->isitmp = 1;
+ retlab->islbl = 1;
+ inlineState.retlab = retlab;
+
+ /* Build the subtree for the inlined function in the form: */
+ /* { //inlinetree block */
+ /* { //inlinetree2 block */
+ /* inline_function_code; */
+ /* retlab: */
+ /* } */
+ /* } */
+ temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
+ copyAstLoc (temptree, tree);
+ temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
+ copyAstLoc (temptree, tree);
+ temptree = newNode (BLOCK, NULL, temptree);
+ copyAstLoc (temptree, tree);
+ inlinetree2 = temptree;
+ inlinetree = newNode (BLOCK, NULL, inlinetree2);
+ copyAstLoc (inlinetree, tree);
+
+ /* To pass parameters to the inlined function, we need some */
+ /* intermediate variables. This avoids scoping problems */
+ /* when the parameter declaration names are used differently */
+ /* during the function call. For example, a function */
+ /* declared as func(int x, int y) but called as func(y,x). */
+ /* { //inlinetree block */
+ /* type1 temparg1 = argument1; */
+ /* ... */
+ /* typen tempargn = argumentn; */
+ /* { //inlinetree2 block */
+ /* type1 param1 = temparg1; */
+ /* ... */
+ /* typen paramn = tempargn; */
+ /* inline_function_code; */
+ /* retlab: */
+ /* } */
+ /* } */
+ args = FUNC_ARGS (func->type);
+ argIndex = 0;
+ while (args)
+ {
+ symbol * temparg;
+ ast * assigntree;
+ symbol * parm;
+ ast * passedarg = inlineFindParm (tree->right, argIndex);
+
+ if (!passedarg)
+ {
+ werror(E_TOO_FEW_PARMS);
+ break;
+ }
+
+ temparg = inlineTempVar (args->sym->type, tree->level+1);
+ inlineAddDecl (temparg, inlinetree, FALSE);
+
+ assigntree = newNode ('=',
+ newAst_VALUE (symbolVal (temparg)),
+ passedarg);
+ assigntree->initMode=1; // tell that assignment is initializer
+ inlinetree->right = newNode (NULLOP,
+ assigntree,
+ inlinetree->right);
+
+ parm = copySymbol (args->sym);
+ inlineAddDecl (parm, inlinetree2, FALSE);
+ parm->_isparm = 0;
+
+ assigntree = newNode ('=',
+ newAst_VALUE (symbolVal (parm)),
+ newAst_VALUE (symbolVal (temparg)));
+ assigntree->initMode=1; // tell that assignment is initializer
+ inlinetree2->right = newNode (NULLOP,
+ assigntree,
+ inlinetree2->right);
+
+ args = args->next;
+ argIndex++;
+ }
+
+ /* Handle the return type */
+ if (!IS_VOID (func->type->next))
+ {
+ /* Create a temporary symbol to hold the return value and */
+ /* join it with the inlined function using the comma */
+ /* operator. The fixupInline function will take care of */
+ /* changing return statements into assignments to retsym. */
+ /* (parameter passing and return label omitted for clarity) */
+ /* rettype retsym; */
+ /* ... */
+ /* {{inline_function_code}}, retsym */
+
+ retsym = inlineTempVar (func->type->next, tree->level);
+ inlineAddDecl (retsym, block, TRUE);
+
+ tree->opval.op = ',';
+ tree->left = inlinetree;
+ tree->right = newAst_VALUE (symbolVal (retsym));
+ }
+ else
+ {
+ tree->opval.op = NULLOP;
+ tree->left = NULL;
+ tree->right = inlinetree;
+ }
+ inlineState.retsym = retsym;
+
+ /* Renumber the various internal counters on the inlined */
+ /* function's tree nodes and symbols. Add the inlined */
+ /* function's local variables to the appropriate scope(s). */
+ /* Convert inlined return statements to an assignment to */
+ /* retsym (if needed) and a goto retlab. */
+ fixupInline (inlinetree, inlinetree->level);
+ inlineState.count++;
+ }
+ }
+
+ /* Recursively continue to search for functions to inline. */
+ if (IS_AST_OP (tree))
+ {
+ if (tree->opval.op == BLOCK)
+ block = tree;
+
+ if (tree->left)
+ expandInlineFuncs (tree->left, block);
+ if (tree->right)
+ expandInlineFuncs (tree->right, block);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* createFunction - This is the key node that calls the iCode for */
/* generating the code for a function. Note code */
actually means we are now compiling the compiler
support routine */
if (name->cdef)
- {
- addSet (&publics, name);
- }
+ {
+ addSet (&publics, name);
+ }
}
else
{
- addSymChain (name);
+ addSymChain (&name);
allocVariables (name);
}
- name->lastLine = mylineno;
+ name->lastLine = lexLineno;
currFunc = name;
/* set the stack pointer */
- /* PENDING: check this for the mcs51 */
- stackPtr = -port->stack.direction * port->stack.call_overhead;
+ stackPtr = -port->stack.direction * port->stack.call_overhead;
+ xstackPtr = 0;
+
if (IFFUNC_ISISR (name->type))
stackPtr -= port->stack.direction * port->stack.isr_overhead;
- if (IFFUNC_ISREENT (name->type) || options.stackAuto)
- stackPtr -= port->stack.direction * port->stack.reent_overhead;
- xstackPtr = -port->stack.direction * port->stack.call_overhead;
+ if (IFFUNC_ISREENT (name->type) || options.stackAuto)
+ {
+ if (options.useXstack)
+ xstackPtr -= port->stack.direction * port->stack.reent_overhead;
+ else
+ stackPtr -= port->stack.direction * port->stack.reent_overhead;
+ }
- fetype = getSpec (name->type); /* get the specifier for the function */
+ fetype = getSpec (name->type); /* get the specifier for the function */
/* if this is a reentrant function then */
if (IFFUNC_ISREENT (name->type))
reentrant++;
- allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
+ inlineState.count = 0;
+ expandInlineFuncs (body, NULL);
+
+ if (FUNC_ISINLINE (name->type))
+ name->funcTree = copyAst (body);
+
+ allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
/* do processing for parameters that are passed in registers */
processRegParms (FUNC_ARGS(name->type), body);
stackPtr = 0;
xstackPtr = -1;
+ gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
+
/* allocate & autoinit the block variables */
processBlockVars (body, &stack, ALLOCATE);
+ /* 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;
- /* 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 */
-
-
- ex = newAst_VALUE (symbolVal (name)); /* create name */
+ ex = newAst_VALUE (symbolVal (name)); /* create name */
ex = newNode (FUNCTION, ex, body);
ex->values.args = FUNC_ARGS(name->type);
ex->decorated=1;
- if (options.dump_tree) PA(ex);
+ if (options.dump_tree)
+ PA(ex);
if (fatalError)
- {
- werror (E_FUNC_NO_CODE, name->name);
- goto skipall;
- }
+ goto skipall;
+
+ /* Do not generate code for inline functions unless extern also. */
+#if 0
+ if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
+ goto skipall;
+#else
+ /* Temporary hack: always generate code for static inline functions. */
+ /* Ideally static inline functions should only be generated if needed. */
+ if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
+ goto skipall;
+#endif
/* create the node & generate intermediate code */
GcurMemmap = code;
- codeOutFile = code->oFile;
+ codeOutBuf = &code->oBuf;
piCode = iCodeFromAst (ex);
+ name->generated = 1;
if (fatalError)
- {
- werror (E_FUNC_NO_CODE, name->name);
- goto skipall;
- }
+ goto skipall;
eBBlockFromiCode (piCode);
if (staticAutos)
{
GcurMemmap = statsg;
- codeOutFile = statsg->oFile;
- eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
+ codeOutBuf = &statsg->oBuf;
+ eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
staticAutos = NULL;
}
/* we are done freeup memory & cleanup */
noLineno--;
- if (port->reset_labelKey) labelKey = 1;
+ if (port->reset_labelKey)
+ labelKey = 1;
name->key = 0;
FUNC_HASBODY(name->type) = 1;
addSet (&operKeyReset, name);
}
-#define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
+#define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
/*-----------------------------------------------------------------*/
/* ast_print : prints the ast (for debugging purposes) */
/*-----------------------------------------------------------------*/
void ast_print (ast * tree, FILE *outfile, int indent)
{
- if (!tree) return ;
-
- /* can print only decorated trees */
- if (!tree->decorated) return;
-
- /* if any child is an error | this one is an error do nothing */
- if (tree->isError ||
- (tree->left && tree->left->isError) ||
- (tree->right && tree->right->isError)) {
- fprintf(outfile,"ERROR_NODE(%p)\n",tree);
- }
-
-
- /* print the line */
- /* if not block & function */
- if (tree->type == EX_OP &&
- (tree->opval.op != FUNCTION &&
- tree->opval.op != BLOCK &&
- tree->opval.op != NULLOP)) {
- }
-
- if (tree->opval.op == FUNCTION) {
- int arg=0;
- value *args=FUNC_ARGS(tree->left->opval.val->type);
- fprintf(outfile,"FUNCTION (%s=%p) type (",
- tree->left->opval.val->name, tree);
- printTypeChain (tree->left->opval.val->type->next,outfile);
- fprintf(outfile,") args (");
- do {
- if (arg) {
- fprintf (outfile, ", ");
- }
- printTypeChain (args ? args->type : NULL, outfile);
- arg++;
- args= args ? args->next : NULL;
- } while (args);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent);
- ast_print(tree->right,outfile,indent);
- return ;
- }
- if (tree->opval.op == BLOCK) {
- symbol *decls = tree->values.sym;
- INDENT(indent,outfile);
- fprintf(outfile,"{\n");
- while (decls) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
- decls->name, decls);
- printTypeChain(decls->type,outfile);
- fprintf(outfile,")\n");
-
- decls = decls->next;
- }
- ast_print(tree->right,outfile,indent+2);
- INDENT(indent,outfile);
- fprintf(outfile,"}\n");
- return;
- }
- if (tree->opval.op == NULLOP) {
- ast_print(tree->left,outfile,indent);
- ast_print(tree->right,outfile,indent);
- return ;
- }
- INDENT(indent,outfile);
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* leaf has been reached */
- /*----------------------------*/
- /* if this is of type value */
- /* just get the type */
- if (tree->type == EX_VALUE) {
-
- if (IS_LITERAL (tree->opval.val->etype)) {
- fprintf(outfile,"CONSTANT (%p) value = ", tree);
- if (SPEC_USIGN (tree->opval.val->etype))
- fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
- else
- fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
- fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
- floatFromVal(tree->opval.val));
- } else if (tree->opval.val->sym) {
- /* if the undefined flag is set then give error message */
- if (tree->opval.val->sym->undefined) {
- fprintf(outfile,"UNDEFINED SYMBOL ");
- } else {
- fprintf(outfile,"SYMBOL ");
- }
- fprintf(outfile,"(%s=%p)",
- tree->opval.val->sym->name,tree);
- }
- if (tree->ftype) {
- fprintf(outfile," type (");
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- } else {
- fprintf(outfile,"\n");
- }
- return ;
- }
-
- /* if type link for the case of cast */
- if (tree->type == EX_LINK) {
- fprintf(outfile,"TYPENODE (%p) type = (",tree);
- printTypeChain(tree->opval.lnk,outfile);
- fprintf(outfile,")\n");
- return ;
- }
-
-
- /* depending on type of operator do */
-
- switch (tree->opval.op) {
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* array node */
- /*----------------------------*/
- case '[':
- fprintf(outfile,"ARRAY_OP (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* struct/union */
- /*----------------------------*/
- case '.':
- fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* struct/union pointer */
- /*----------------------------*/
- case PTR_OP:
- fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* ++/-- operation */
- /*----------------------------*/
- case INC_OP:
- if (tree->left)
- fprintf(outfile,"post-");
- else
- fprintf(outfile,"pre-");
- fprintf(outfile,"INC_OP (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2); /* postincrement case */
- ast_print(tree->right,outfile,indent+2); /* preincrement case */
- return ;
-
- case DEC_OP:
- if (tree->left)
- fprintf(outfile,"post-");
- else
- fprintf(outfile,"pre-");
- fprintf(outfile,"DEC_OP (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2); /* postdecrement case */
- ast_print(tree->right,outfile,indent+2); /* predecrement case */
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* bitwise and */
- /*----------------------------*/
- case '&':
- if (tree->right) {
- fprintf(outfile,"& (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- } else {
- fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- }
- return ;
- /*----------------------------*/
- /* bitwise or */
- /*----------------------------*/
- case '|':
- fprintf(outfile,"OR (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* bitwise xor */
- /*----------------------------*/
- case '^':
- fprintf(outfile,"XOR (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* division */
- /*----------------------------*/
- case '/':
- fprintf(outfile,"DIV (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* modulus */
- /*----------------------------*/
- case '%':
- fprintf(outfile,"MOD (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* address dereference */
- /*----------------------------*/
- case '*': /* can be unary : if right is null then unary operation */
- if (!tree->right) {
- fprintf(outfile,"DEREF (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- }
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* multiplication */
- /*----------------------------*/
- fprintf(outfile,"MULT (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* unary '+' operator */
- /*----------------------------*/
- case '+':
- /* if unary plus */
- if (!tree->right) {
- fprintf(outfile,"UPLUS (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- } else {
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* addition */
- /*----------------------------*/
- fprintf(outfile,"ADD (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- }
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* unary '-' */
- /*----------------------------*/
- case '-': /* can be unary */
- if (!tree->right) {
- fprintf(outfile,"UMINUS (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- } else {
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* subtraction */
- /*----------------------------*/
- fprintf(outfile,"SUB (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- }
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* compliment */
- /*----------------------------*/
- case '~':
- fprintf(outfile,"COMPL (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* not */
- /*----------------------------*/
- case '!':
- fprintf(outfile,"NOT (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* shift */
- /*----------------------------*/
- case RRC:
- fprintf(outfile,"RRC (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
-
- case RLC:
- fprintf(outfile,"RLC (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- case SWAP:
- fprintf(outfile,"SWAP (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- case GETHBIT:
- fprintf(outfile,"GETHBIT (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- case LEFT_OP:
- fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case RIGHT_OP:
- fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* casting */
- /*----------------------------*/
- case CAST: /* change the type */
- fprintf(outfile,"CAST (%p) from type (",tree);
- printTypeChain(tree->right->ftype,outfile);
- fprintf(outfile,") to type (");
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- case AND_OP:
- fprintf(outfile,"ANDAND (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case OR_OP:
- fprintf(outfile,"OROR (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* comparison operators */
- /*----------------------------*/
- case '>':
- fprintf(outfile,"GT(>) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case '<':
- fprintf(outfile,"LT(<) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case LE_OP:
- fprintf(outfile,"LE(<=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case GE_OP:
- fprintf(outfile,"GE(>=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case EQ_OP:
- fprintf(outfile,"EQ(==) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
- case NE_OP:
- fprintf(outfile,"NE(!=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* sizeof */
- /*----------------------------*/
- case SIZEOF: /* evaluate wihout code generation */
- fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* conditional operator '?' */
- /*----------------------------*/
- case '?':
- fprintf(outfile,"QUEST(?) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
-
- case ':':
- fprintf(outfile,"COLON(:) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return ;
-
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* assignment operators */
- /*----------------------------*/
- case MUL_ASSIGN:
- fprintf(outfile,"MULASS(*=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case DIV_ASSIGN:
- fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case AND_ASSIGN:
- fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case OR_ASSIGN:
- fprintf(outfile,"ORASS(|=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case XOR_ASSIGN:
- fprintf(outfile,"XORASS(^=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case RIGHT_ASSIGN:
- fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case LEFT_ASSIGN:
- fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* -= operator */
- /*----------------------------*/
- case SUB_ASSIGN:
- fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* += operator */
- /*----------------------------*/
- case ADD_ASSIGN:
- fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* straight assignemnt */
- /*----------------------------*/
- case '=':
- fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* comma operator */
- /*----------------------------*/
- case ',':
- fprintf(outfile,"COMMA(,) (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* function call */
- /*----------------------------*/
- case CALL:
- case PCALL:
- fprintf(outfile,"CALL (%p) type (",tree);
- printTypeChain(tree->ftype,outfile);
- fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent+2);
- return;
- case PARAM:
- fprintf(outfile,"PARMS\n");
- ast_print(tree->left,outfile,indent+2);
- if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
- ast_print(tree->right,outfile,indent+2);
- }
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* return statement */
- /*----------------------------*/
- case RETURN:
- fprintf(outfile,"RETURN (%p) type (",tree);
- if (tree->right) {
- printTypeChain(tree->right->ftype,outfile);
- }
- fprintf(outfile,")\n");
- ast_print(tree->right,outfile,indent+2);
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* label statement */
- /*----------------------------*/
- case LABEL :
- fprintf(outfile,"LABEL (%p)\n",tree);
- ast_print(tree->left,outfile,indent+2);
- ast_print(tree->right,outfile,indent);
- return;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* switch statement */
- /*----------------------------*/
- case SWITCH:
- {
- value *val;
- fprintf(outfile,"SWITCH (%p) ",tree);
- ast_print(tree->left,outfile,0);
- for (val = tree->values.switchVals.swVals; val ; val = val->next) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
- (int) floatFromVal(val),
- tree->values.switchVals.swNum,
- (int) floatFromVal(val));
- }
- ast_print(tree->right,outfile,indent);
- }
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* ifx Statement */
- /*----------------------------*/
- case IFX:
- fprintf(outfile,"IF (%p) \n",tree);
- ast_print(tree->left,outfile,indent+2);
- if (tree->trueLabel) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
- }
- if (tree->falseLabel) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
- }
- ast_print(tree->right,outfile,indent+2);
- return ;
- /*----------------------------*/
- /* goto Statement */
- /*----------------------------*/
- case GOTO:
- fprintf(outfile,"GOTO (%p) \n",tree);
- ast_print(tree->left,outfile,indent+2);
- fprintf(outfile,"\n");
- return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* for Statement */
- /*----------------------------*/
- case FOR:
- fprintf(outfile,"FOR (%p) \n",tree);
- if (AST_FOR( tree, initExpr)) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"INIT EXPR ");
- ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
- }
- if (AST_FOR( tree, condExpr)) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"COND EXPR ");
- ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
- }
- if (AST_FOR( tree, loopExpr)) {
- INDENT(indent+2,outfile);
- fprintf(outfile,"LOOP EXPR ");
- ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
- }
- fprintf(outfile,"FOR LOOP BODY \n");
- ast_print(tree->left,outfile,indent+2);
- return ;
- case CRITICAL:
- fprintf(outfile,"CRITICAL (%p) \n",tree);
- ast_print(tree->left,outfile,indent+2);
- default:
- return ;
- }
+ if (!tree) return ;
+
+ /* can print only decorated trees */
+ if (!tree->decorated) return;
+
+ /* if any child is an error | this one is an error do nothing */
+ if (tree->isError ||
+ (tree->left && tree->left->isError) ||
+ (tree->right && tree->right->isError)) {
+ fprintf(outfile,"ERROR_NODE(%p)\n",tree);
+ }
+
+
+ /* print the line */
+ /* if not block & function */
+ if (tree->type == EX_OP &&
+ (tree->opval.op != FUNCTION &&
+ tree->opval.op != BLOCK &&
+ tree->opval.op != NULLOP)) {
+ }
+
+ if (tree->opval.op == FUNCTION) {
+ int arg=0;
+ value *args=FUNC_ARGS(tree->left->opval.val->type);
+ fprintf(outfile,"FUNCTION (%s=%p) type (",
+ tree->left->opval.val->name, tree);
+ printTypeChain (tree->left->opval.val->type->next,outfile);
+ fprintf(outfile,") args (");
+ do {
+ if (arg) {
+ fprintf (outfile, ", ");
+ }
+ printTypeChain (args ? args->type : NULL, outfile);
+ arg++;
+ args= args ? args->next : NULL;
+ } while (args);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent);
+ ast_print(tree->right,outfile,indent);
+ return ;
+ }
+ if (tree->opval.op == BLOCK) {
+ symbol *decls = tree->values.sym;
+ INDENT(indent,outfile);
+ fprintf(outfile,"{\n");
+ while (decls) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
+ decls->name, decls);
+ printTypeChain(decls->type,outfile);
+ fprintf(outfile,")\n");
+
+ decls = decls->next;
+ }
+ ast_print(tree->right,outfile,indent+2);
+ INDENT(indent,outfile);
+ fprintf(outfile,"}\n");
+ return;
+ }
+ if (tree->opval.op == NULLOP) {
+ ast_print(tree->left,outfile,indent);
+ ast_print(tree->right,outfile,indent);
+ return ;
+ }
+ INDENT(indent,outfile);
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* leaf has been reached */
+ /*----------------------------*/
+ /* if this is of type value */
+ /* just get the type */
+ if (tree->type == EX_VALUE) {
+
+ if (IS_LITERAL (tree->opval.val->etype)) {
+ fprintf(outfile,"CONSTANT (%p) value = ", tree);
+ if (SPEC_USIGN (tree->opval.val->etype))
+ fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
+ else
+ fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
+ fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
+ floatFromVal(tree->opval.val));
+ } else if (tree->opval.val->sym) {
+ /* if the undefined flag is set then give error message */
+ if (tree->opval.val->sym->undefined) {
+ fprintf(outfile,"UNDEFINED SYMBOL ");
+ } else {
+ fprintf(outfile,"SYMBOL ");
+ }
+ fprintf(outfile,"(%s=%p @ %p)",
+ tree->opval.val->sym->name, tree, tree->opval.val->sym);
+ }
+ if (tree->ftype) {
+ fprintf(outfile," type (");
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ } else {
+ fprintf(outfile,"\n");
+ }
+ return ;
+ }
+
+ /* if type link for the case of cast */
+ if (tree->type == EX_LINK) {
+ fprintf(outfile,"TYPENODE (%p) type = (",tree);
+ printTypeChain(tree->opval.lnk,outfile);
+ fprintf(outfile,")\n");
+ return ;
+ }
+
+
+ /* depending on type of operator do */
+
+ switch (tree->opval.op) {
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* array node */
+ /*----------------------------*/
+ case '[':
+ fprintf(outfile,"ARRAY_OP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* struct/union */
+ /*----------------------------*/
+ case '.':
+ fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* struct/union pointer */
+ /*----------------------------*/
+ case PTR_OP:
+ fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* ++/-- operation */
+ /*----------------------------*/
+ case INC_OP:
+ if (tree->left)
+ fprintf(outfile,"post-");
+ else
+ fprintf(outfile,"pre-");
+ fprintf(outfile,"INC_OP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2); /* postincrement case */
+ ast_print(tree->right,outfile,indent+2); /* preincrement case */
+ return ;
+
+ case DEC_OP:
+ if (tree->left)
+ fprintf(outfile,"post-");
+ else
+ fprintf(outfile,"pre-");
+ fprintf(outfile,"DEC_OP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2); /* postdecrement case */
+ ast_print(tree->right,outfile,indent+2); /* predecrement case */
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* bitwise and */
+ /*----------------------------*/
+ case '&':
+ if (tree->right) {
+ fprintf(outfile,"& (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ } else {
+ fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ }
+ return ;
+ /*----------------------------*/
+ /* bitwise or */
+ /*----------------------------*/
+ case '|':
+ fprintf(outfile,"OR (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* bitwise xor */
+ /*----------------------------*/
+ case '^':
+ fprintf(outfile,"XOR (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* division */
+ /*----------------------------*/
+ case '/':
+ fprintf(outfile,"DIV (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* modulus */
+ /*----------------------------*/
+ case '%':
+ fprintf(outfile,"MOD (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* address dereference */
+ /*----------------------------*/
+ case '*': /* can be unary : if right is null then unary operation */
+ if (!tree->right) {
+ fprintf(outfile,"DEREF (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ }
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* multiplication */
+ /*----------------------------*/
+ fprintf(outfile,"MULT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* unary '+' operator */
+ /*----------------------------*/
+ case '+':
+ /* if unary plus */
+ if (!tree->right) {
+ fprintf(outfile,"UPLUS (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ } else {
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* addition */
+ /*----------------------------*/
+ fprintf(outfile,"ADD (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ }
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* unary '-' */
+ /*----------------------------*/
+ case '-': /* can be unary */
+ if (!tree->right) {
+ fprintf(outfile,"UMINUS (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ } else {
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* subtraction */
+ /*----------------------------*/
+ fprintf(outfile,"SUB (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ }
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* complement */
+ /*----------------------------*/
+ case '~':
+ fprintf(outfile,"COMPL (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* not */
+ /*----------------------------*/
+ case '!':
+ fprintf(outfile,"NOT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* shift */
+ /*----------------------------*/
+ case RRC:
+ fprintf(outfile,"RRC (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+
+ case RLC:
+ fprintf(outfile,"RLC (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ case SWAP:
+ fprintf(outfile,"SWAP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ case GETHBIT:
+ fprintf(outfile,"GETHBIT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ case GETABIT:
+ fprintf(outfile,"GETABIT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case GETBYTE:
+ fprintf(outfile,"GETBYTE (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case GETWORD:
+ fprintf(outfile,"GETWORD (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case LEFT_OP:
+ fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case RIGHT_OP:
+ fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* casting */
+ /*----------------------------*/
+ case CAST: /* change the type */
+ fprintf(outfile,"CAST (%p) from type (",tree);
+ printTypeChain(tree->right->ftype,outfile);
+ fprintf(outfile,") to type (");
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ case AND_OP:
+ fprintf(outfile,"ANDAND (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case OR_OP:
+ fprintf(outfile,"OROR (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* comparison operators */
+ /*----------------------------*/
+ case '>':
+ fprintf(outfile,"GT(>) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case '<':
+ fprintf(outfile,"LT(<) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case LE_OP:
+ fprintf(outfile,"LE(<=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case GE_OP:
+ fprintf(outfile,"GE(>=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case EQ_OP:
+ fprintf(outfile,"EQ(==) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case NE_OP:
+ fprintf(outfile,"NE(!=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* sizeof */
+ /*----------------------------*/
+ case SIZEOF: /* evaluate wihout code generation */
+ fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* conditional operator '?' */
+ /*----------------------------*/
+ case '?':
+ fprintf(outfile,"QUEST(?) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+
+ case ':':
+ fprintf(outfile,"COLON(:) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* assignment operators */
+ /*----------------------------*/
+ case MUL_ASSIGN:
+ fprintf(outfile,"MULASS(*=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case DIV_ASSIGN:
+ fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case AND_ASSIGN:
+ fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case OR_ASSIGN:
+ fprintf(outfile,"ORASS(|=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case XOR_ASSIGN:
+ fprintf(outfile,"XORASS(^=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case RIGHT_ASSIGN:
+ fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case LEFT_ASSIGN:
+ fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* -= operator */
+ /*----------------------------*/
+ case SUB_ASSIGN:
+ fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* += operator */
+ /*----------------------------*/
+ case ADD_ASSIGN:
+ fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* straight assignemnt */
+ /*----------------------------*/
+ case '=':
+ fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* comma operator */
+ /*----------------------------*/
+ case ',':
+ fprintf(outfile,"COMMA(,) (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* function call */
+ /*----------------------------*/
+ case CALL:
+ case PCALL:
+ fprintf(outfile,"CALL (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return;
+ case PARAM:
+ fprintf(outfile,"PARMS\n");
+ ast_print(tree->left,outfile,indent+2);
+ if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
+ ast_print(tree->right,outfile,indent+2);
+ }
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* return statement */
+ /*----------------------------*/
+ case RETURN:
+ fprintf(outfile,"RETURN (%p) type (",tree);
+ if (tree->right) {
+ printTypeChain(tree->right->ftype,outfile);
+ }
+ fprintf(outfile,")\n");
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* label statement */
+ /*----------------------------*/
+ case LABEL :
+ fprintf(outfile,"LABEL (%p)\n",tree);
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent);
+ return;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* switch statement */
+ /*----------------------------*/
+ case SWITCH:
+ {
+ value *val;
+ fprintf(outfile,"SWITCH (%p) ",tree);
+ ast_print(tree->left,outfile,0);
+ for (val = tree->values.switchVals.swVals; val ; val = val->next) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
+ (int) ulFromVal(val),
+ tree->values.switchVals.swNum,
+ (int) ulFromVal(val));
+ }
+ ast_print(tree->right,outfile,indent);
+ }
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* ifx Statement */
+ /*----------------------------*/
+ case IFX:
+ fprintf(outfile,"IF (%p) \n",tree);
+ ast_print(tree->left,outfile,indent+2);
+ if (tree->trueLabel) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
+ }
+ if (tree->falseLabel) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
+ }
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ /*----------------------------*/
+ /* goto Statement */
+ /*----------------------------*/
+ case GOTO:
+ fprintf(outfile,"GOTO (%p) \n",tree);
+ ast_print(tree->left,outfile,indent+2);
+ fprintf(outfile,"\n");
+ return ;
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* for Statement */
+ /*----------------------------*/
+ case FOR:
+ fprintf(outfile,"FOR (%p) \n",tree);
+ if (AST_FOR( tree, initExpr)) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"INIT EXPR ");
+ ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
+ }
+ if (AST_FOR( tree, condExpr)) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"COND EXPR ");
+ ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
+ }
+ if (AST_FOR( tree, loopExpr)) {
+ INDENT(indent+2,outfile);
+ fprintf(outfile,"LOOP EXPR ");
+ ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
+ }
+ fprintf(outfile,"FOR LOOP BODY \n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
+ case CRITICAL:
+ fprintf(outfile,"CRITICAL (%p) \n",tree);
+ ast_print(tree->left,outfile,indent+2);
+ default:
+ return ;
+ }
}
void PA(ast *t)
{
- ast_print(t,stdout,0);
+ ast_print(t,stdout,0);
}
-
-
/*-----------------------------------------------------------------*/
/* astErrors : returns non-zero if errors present in tree */
/*-----------------------------------------------------------------*/
int astErrors(ast *t)
{
int errors=0;
-
+
if (t)
{
if (t->isError)
errors++;
-
+
if (t->type == EX_VALUE
&& t->opval.val->sym
&& t->opval.val->sym->undefined)
errors += astErrors(t->left);
errors += astErrors(t->right);
}
-
+
return errors;
}