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
{
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);
+ }
}
{
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;
}
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);
}
/*-----------------------------------------------------------------*/
static int
processParms (ast *func,
- value *defParm,
- ast **actParm,
- int *parmNumber, /* unused, although updated */
- bool rightmost)
+ 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)
return 0;
functype = func->ftype->next;
else
functype = func->ftype;
-
- /* if the function is being called via a pointer & */
- /* it has not been defined a reentrant then we cannot */
- /* have parameters */
- if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+
+ /* 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);
- fatalError++;
- 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 */
{
(*actParm)->decorated = 1;
return (processParms (func, defParm,
- &(*actParm)->left, parmNumber, FALSE) ||
- processParms (func, defParm ? defParm->next : NULL,
- &(*actParm)->right, parmNumber, rightmost));
+ &(*actParm)->left, parmNumber, FALSE) ||
+ processParms (func, defParm ? defParm->next : NULL,
+ &(*actParm)->right, parmNumber, rightmost));
}
else if (defParm) /* not vararg */
{
* supply enough.
*/
if (rightmost && defParm->next)
- {
- werror (E_TOO_FEW_PARMS);
- return 1;
- }
+ {
+ werror (E_TOO_FEW_PARMS);
+ return 1;
+ }
}
/* decorate parameter */
- resultType = defParm ? getResultTypeFromType (defParm->etype) :
+ resultType = defParm ? getResultTypeFromType (defParm->type) :
RESULT_TYPE_NONE;
*actParm = decorateType (*actParm, resultType);
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;
/* If it's a char, upcast to int. */
if (IS_INTEGRAL (ftype)
- && (getSize (ftype) < (unsigned) INTSIZE))
- {
- 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. */
(*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;
return 0;
resolveSymbols (*actParm);
-
+
/* the parameter type must be at least castable */
if (compareType (defParm->type, (*actParm)->ftype) == 0)
{
resultType = getResultTypeFromType (defParm->etype);
pTree = resolveSymbols (copyAst (*actParm));
-
+
/* now change the current one to a cast */
(*actParm)->type = EX_OP;
(*actParm)->opval.op = CAST;
(*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;
}
if (ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
- return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
+ iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+ 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;
{
/* if we have come to end */
if (!iloop)
- break;
+ 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);
+ lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+ rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+ iloop, rast, rootValue)),
+ RESULT_TYPE_NONE);
+
}
- if (iloop) {
- werrorfl (sym->opval.val->sym->fileDef, 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;
/* 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)
- {
- werror (E_INIT_STRUCT, "");
- return NULL;
- }
+ /* not the special case */
+ if (ilist->type != INIT_DEEP)
+ {
+ werror (E_INIT_STRUCT, "");
+ return NULL;
+ }
+
+ iloop = ilist->init.deep;
+ lcnt = DCL_ELEM (type);
- iloop = ilist->init.deep;
- lcnt = DCL_ELEM (type);
+ if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+ {
+ ast *aSym;
- if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
- {
- 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;
- char *filename=sym->opval.val->sym->fileDef;
-
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", 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;
- char *filename=sym->opval.val->sym->fileDef;
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-
- break;
- }
- }
- }
+ 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_TYPE_NONE);
+ rast = createIval (aSym, type->next, iloop, rast, rootValue);
+ iloop = (iloop ? iloop->next : NULL);
+ if (!iloop)
+ {
+ break;
+ }
+
+ /* no of elements given and we */
+ /* have generated for all of them */
+ if (!--lcnt)
+ {
+ // 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);
- /* if we have not been given a size */
- if (!DCL_ELEM (type))
+ break;
+ }
+ }
+ }
+
+ /* 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 ((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;
- }
+ unsigned int i = 0;
+ unsigned int symsize = getSize (type);
+
+ size = getSize (iexpr->ftype);
+ if (symsize && size>symsize)
+ {
+ if (size>(symsize+1))
+ {
+ 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))));
- s++;
- }
+ {
+ rast = newNode (NULLOP,
+ rast,
+ newNode ('=',
+ newNode ('[', sym,
+ newAst_VALUE (valueFromLit ((float) i))),
+ newAst_VALUE (valueFromLit (*s))));
+ 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 (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 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 *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)
/* resolve the symbols in the ival */
if (sym->ival)
- resolveIvalSym (sym->ival, sym->type);
+ 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 (sym->fileDef, 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 (sym->fileDef, 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 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 */
/*-----------------------------------------------------------------*/
-bool
+bool
isConformingBody (ast * pbody, symbol * sym, ast * body)
{
/* if we reach the end or a leaf then true */
if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
return TRUE;
-
+
/* if anything else is "volatile" */
if (IS_VOLATILE (TETYPE (pbody)))
return FALSE;
/*------------------------------------------------------------------*/
case '[':
// 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 '&':
/* 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;
return isConformingBody (pbody->left, sym, body) &&
- isConformingBody (pbody->right, sym, body);
+ isConformingBody (pbody->right, sym, body);
case MUL_ASSIGN:
case DIV_ASSIGN:
/*----------------------------*/
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 paramater then ok */
+ if (sym->level && !astHasSymbol(pbody->right,sym))
+ return TRUE;
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;
/* 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;
}
if (IS_BITFIELD (type))
{
int blen = SPEC_BLEN (type);
-
+
if (blen <= 1)
return RESULT_TYPE_BIT;
if (blen <= 8)
}
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 ast *
-addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
{
sym_link *newLink;
bool upCasted = FALSE;
-
+
switch (resultType)
{
case RESULT_TYPE_NONE:
- /* char: promote to int */
- if (!upcast ||
- getSize (tree->etype) >= INTSIZE)
- return tree;
- newLink = newIntLink();
- upCasted = TRUE;
- break;
+ /* 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 (IS_CHAR (tree->etype) ||
- IS_FLOAT(tree->etype))
- return tree;
- 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 tree;
- newLink = newIntLink();
- upCasted = TRUE;
- 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 tree;
- /* return type is long, float: promote char to int */
- if (getSize (tree->etype) >= INTSIZE)
- return tree;
- newLink = newIntLink();
- upCasted = TRUE;
- 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 tree;
+ return tree;
}
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 */
{
switch (tree->opval.op)
{
+ case AND_OP:
+ case OR_OP:
+ case '!':
case '=':
case '?':
case ':':
case '|':
case '^':
case '~':
+ case LEFT_OP:
+ case LABEL:
+ return resultType;
case '*':
case '+':
case '-':
- case LABEL:
- return resultType;
+ 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;
+ return RESULT_TYPE_IFX;
default:
- return RESULT_TYPE_NONE;
+ return RESULT_TYPE_NONE;
}
}
{
case '=':
case CAST:
- if (IS_PTR (LTYPE (tree)))
- return RESULT_TYPE_NONE;
- else
- return getResultTypeFromType (LETYPE (tree));
+ 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)) <= 256)
- return RESULT_TYPE_CHAR;
- return resultType;
+ 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;
- }
- }
- }
-
- return tree;
+ {
+ /* 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 type link for the case of cast */
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
upon tree->opval.op, if resultType can be propagated */
resultTypeProp = resultTypePropagate (tree, resultType);
- if (tree->opval.op == '?')
+ if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
dtl = decorateType (tree->left, RESULT_TYPE_IFX);
else
dtl = decorateType (tree->left, resultTypeProp);
{
/* 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;
- }
+ 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. */
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;
- default:
- dtr = decorateType (tree->right, resultTypeProp);
- break;
+ /* 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
switch (tree->opval.op)
{
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* array node */
- /*----------------------------*/
+ /*------------------------------------------------------------------*/
+ /*----------------------------*/
+ /* array node */
+ /*----------------------------*/
case '[':
/* 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) floatFromVal (valFromType (RETYPE (tree)));
- int arraySize = DCL_ELEM (LTYPE (tree));
- if (arraySize && arrayIndex >= arraySize)
- {
- werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
- }
- }
+ {
+ 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);
- }
-
- TTYPE (tree) = computeType (LTYPE (tree),
- RTYPE (tree),
- resultType,
- tree->opval.op);
- 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)
- {
- DEBUG_CF("&")
- ast *tTree = litTree->left;
- litTree->left = tree->right;
- tree->right = tTree;
- /* both operands in tTree are literal now */
- decorateType (parent, resultType);
- }
- }
-
- 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)
- {
- DEBUG_CF("|")
- ast *tTree = litTree->left;
- litTree->left = tree->right;
- tree->right = tTree;
- /* both operands in tTree are literal now */
- decorateType (parent, resultType);
- }
+ {
+ 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)
- {
- DEBUG_CF("^")
- ast *tTree = litTree->left;
- litTree->left = tree->right;
- tree->right = tTree;
- /* both operands in litTree are literal now */
- decorateType (parent, resultType);
- }
+ {
+ 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;
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType,
- tree->opval.op));
+
+ 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),
- resultType,
- tree->opval.op));
+ 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 */
- DEBUG_CF("div r")
- litTree->right = newNode ('*',
- litTree->right,
- copyAst (tree->right));
- litTree->right->lineno = tree->lineno;
-
- tree->right->opval.val = constVal ("1");
- decorateType (parent, resultType);
- }
- 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, resultType);
- }
- }
- }
+ && (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),
- resultType,
- tree->opval.op));
+ 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 IPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+ break;
+ case EEPPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
break;
- case ARRAY:
- case FUNCTION:
- break;
- }
- return tree;
- }
+ 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)
- {
- DEBUG_CF("mul")
- ast *tTree = litTree->left;
- litTree->left = tree->right;
- tree->right = tTree;
- /* both operands in litTree are literal now */
- decorateType (parent, resultType);
- }
+ {
+ 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;
- tree->left = addCast (tree->left, resultType, FALSE);
- tree->right = addCast (tree->right, resultType, FALSE);
+ 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));
+ 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;
+ }
/*------------------------------------------------------------------*/
/*----------------------------*/
/* 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->left = addCast (tree->left, resultType, TRUE);
- tree->right = addCast (tree->right, resultType, 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;
- }
+ {
+ 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 */
- 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);
- }
- }
+ {
+ 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
- {
- tree->left = addCast (tree->left, resultType, TRUE);
- tree->right = addCast (tree->right, resultType, TRUE);
+ {
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType,
- tree->opval.op));
- }
-
+ 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->left = addCast (tree->left, resultType, TRUE);
- tree->right = addCast (tree->right, resultType, 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;
- }
+ {
+ 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
- {
- tree->left = addCast (tree->left, resultType, TRUE);
- tree->right = addCast (tree->right, resultType, TRUE);
+ {
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ tree->right = addCast (tree->right, resultTypeProp, TRUE);
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- resultType,
- tree->opval.op));
- }
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ 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 */
- 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);
- }
- }
+ && (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->opval.val = valComplement (valFromType (LETYPE (tree)));
tree->left = NULL;
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return addCast (tree, resultType, TRUE);
+ 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);
}
- tree->left = addCast (tree->left, resultType, TRUE);
+ 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, resultType, TRUE);
-
+ 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)
- {
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- NULL,
- resultType,
- tree->opval.op));
- }
+ {
+ 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;
- }
+ 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;
+ 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)) {
+ symbol * sym = AST_SYMBOL (tree->right->left);
+ unsigned int gptype = 0;
+ unsigned int addr = SPEC_ADDR (sym->etype);
+
+ 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),
- SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
- TTYPE (tree) = tree->opval.val->type;
+ 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;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->values.literalFromCast = 1;
return tree;
}
symbol *element = getStructElement (
SPEC_STRUCT (LETYPE(tree->right->left)),
- AST_SYMBOL(tree->right->left->right)
+ AST_SYMBOL(tree->right->left->right)
);
if (element) {
tree->type = EX_VALUE;
- tree->opval.val = valCastLiteral (
- LTYPE (tree),
- element->offset
+ tree->opval.val = valCastLiteral (
+ LTYPE (tree),
+ element->offset
+ floatFromVal (valFromType (RTYPE (tree->right->left->left)))
);
- TTYPE (tree) = tree->opval.val->type;
+ TTYPE (tree) = tree->opval.val->type;
TETYPE (tree) = getSpec (TTYPE (tree));
- tree->left = NULL;
- tree->right = NULL;
+ 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)) ) {
+ if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
/* rewrite (type *)litaddr
as &temp
and define type at litaddr temp
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;
+ LLVAL (newTree) = 1;
LRVAL (newTree) = 0;
TLVAL (newTree) = 1;
return newTree;
}
- #endif
+ #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));
+ 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;
}
}
case OR_OP:
/* 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 (resultType == RESULT_TYPE_IFX)
- {
- /* the parent is an ifx: */
- /* if (unsigned value) */
- return tree->left;
- }
-
- /* (unsigned value) ? 1 : 0 */
- tree->opval.op = '?';
- tree->right = newNode (':',
- newAst_VALUE (constVal ("1")),
- tree->right); /* val 0 */
- tree->right->lineno = tree->lineno;
- tree->right->left->lineno = tree->lineno;
- decorateType (tree->right, RESULT_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);
+ 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;
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));
- }
+ else
+ return decorateType (tree->right->right, resultTypeProp);
+ }
+
+ tree->right = decorateType (tree->right, resultTypeProp);
+
+ 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)
- {
- werror (E_TYPE_MISMATCH, "conditional operator", " ");
- goto errorTreeReturn;
- }
+ 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);
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),
- RESULT_TYPE_NOPROM,
- tree->opval.op));
+ 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),
- RESULT_TYPE_NOPROM,
- tree->opval.op));
+ 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));
+ 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:
-
+
/* 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 (tree->left->opval.op == '*' && !tree->left->right)
+ tree->left = tree->left->left;
+ }
/* require a function or pointer to function */
- if (!IS_FUNC (LTYPE (tree))
- && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
- {
- werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
- goto errorTreeReturn;
- }
+ if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
+ {
+ werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+ goto errorTreeReturn;
+ }
/* if there are parms, make sure that
parms are decorate / process / reverse only once */
if (!tree->right ||
!tree->right->decorated)
{
- sym_link *functype;
+ sym_link *functype;
parmNumber = 1;
- if (IS_CODEPTR(LTYPE(tree)))
- functype = LTYPE (tree)->next;
+ if (IS_FUNCPTR (LTYPE (tree)))
+ {
+ functype = LTYPE (tree)->next;
+ processFuncPtrArgs (functype);
+ }
else
functype = LTYPE (tree);
{
goto errorTreeReturn;
}
-
- if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
!IFFUNC_ISBUILTIN(functype))
{
reverseParms (tree->right);
/*----------------------------*/
case 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),
+ 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:
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "node PARAM shouldn't be processed here");
- /* but in processParams() */
+ 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;
/*-----------------------------------------------------------------*/
/* 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;
}
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 tree;
-
- if (AST_LIT_VALUE (tree->right) != 1)
- return tree;
+ return NULL;
if (!IS_RIGHT_OP (tree->left))
- return tree;
+ return NULL;
if (!IS_AST_LIT_VALUE (tree->left->right))
- return tree;
+ return NULL;
- if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
- (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
- return tree;
-
- /* make sure the port supports GETHBIT */
- if (port->hasExtBitOp
- && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
- return tree;
+ return tree->left->left;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitAndPowOf2 - helper function */
+/*-----------------------------------------------------------------*/
+static int
+isBitAndPow2 (ast * tree)
+{
+ /* if this is not a bit and */
+ if (!IS_BITAND (tree))
+ return -1;
- return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
+ /* 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));
}
/*-----------------------------------------------------------------*/
-/* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
+/* optimizeGetHbit - get highest order bit of the expression */
/*-----------------------------------------------------------------*/
ast *
-optimizeRRCRLC (ast * root)
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
{
- /* will look for trees of the form
- (?expr << 1) | (?expr >> 7) or
- (?expr >> 7) | (?expr << 1) will make that
- into a RLC : operation ..
- Will also look for
- (?expr >> 1) | (?expr << 7) or
- (?expr << 7) | (?expr >> 1) will make that
- 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 (!IS_BITOR (root))
- return root;
+ unsigned int i, j;
+ ast * expr;
- /* 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
- negative check a lot to improve the efficiency */
- /* (?expr << 1) | (?expr >> 7) */
- if (IS_LEFT_OP (root->left) &&
- IS_RIGHT_OP (root->right))
+ 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;
+
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
+ return tree;
+
+ 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;
+
+ /* make sure the port supports GETABIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
+ return tree;
+
+ 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 GETBYTE */
+ if (port->hasExtBitOp
+ && !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;
+
+ /* 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeRRCRLC (ast * root)
+{
+ /* will look for trees of the form
+ (?expr << 1) | (?expr >> 7) or
+ (?expr >> 7) | (?expr << 1) will make that
+ into a RLC : operation ..
+ Will also look for
+ (?expr >> 1) | (?expr << 7) or
+ (?expr << 7) | (?expr >> 1) will make that
+ into a RRC operation
+ note : by 7 I mean (number of bits required to hold the
+ variable -1 ) */
+ /* 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'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) &&
+ IS_RIGHT_OP (root->right))
{
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)
+{
+ tree->block = currBlockno;
+
+ if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+ {
+ symbol * decls;
+
+ currBlockno++;
+ 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;
+
+ /* 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--;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindMaxBlockno - find maximum block number in an ast tree */
+/*-----------------------------------------------------------------*/
+static int
+inlineFindMaxBlockno (ast * tree, int maxBlockno)
+{
+ int tempBlockno;
+
+ if (!tree)
+ return maxBlockno;
+
+ tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
+ if (tempBlockno > maxBlockno)
+ maxBlockno = tempBlockno;
+
+ tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
+ if (tempBlockno > maxBlockno)
+ maxBlockno = tempBlockno;
+
+ if (tree->block > maxBlockno)
+ maxBlockno = tree->block;
+ return maxBlockno;
+}
+
+
+
+
+/*-----------------------------------------------------------------*/
+/* 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; */
+ /* ... */
+ /* typen tempargn; */
+ /* temparg1 = argument1; */
+ /* ... */
+ /* tempargn = argumentn; */
+ /* { //inlinetree2 block */
+ /* type1 param1; */
+ /* ... */
+ /* typen paramn; */
+ /* param1 = temparg1; */
+ /* ... */
+ /* 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);
+ 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)));
+ 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 */
int stack = 0;
sym_link *fetype;
iCode *piCode = NULL;
+ int savedBlockno;
if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
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;
+ savedBlockno = currBlockno;
+ currBlockno = inlineFindMaxBlockno (body, 0);
+ expandInlineFuncs (body, NULL);
+ currBlockno = savedBlockno;
+
+ 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;
}
}
-#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;
}