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 *optimizeGetAbit (ast *, RESULT_TYPE);
ast *optimizeGetByte (ast *, RESULT_TYPE);
ast *optimizeGetWord (ast *, RESULT_TYPE);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+static ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
int inInitMode = 0;
memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
-FILE *codeOutFile;
-int
+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;
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;
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)
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;
}
/* 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)
{
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 *
funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
{
-
+
symbol *sym;
int i ;
/* create the symbol */
sym = newSymbol (name, 0);
-
+
/* setup return value */
sym->type = newLink (DECLARATOR);
DCL_TYPE (sym->type) = FUNCTION;
sym->type->next = typeFromStr(rtype);
sym->etype = getSpec (sym->type);
-
+
/* if arguments required */
if (nArgs) {
value *args;
args = FUNC_ARGS(sym->type) = newValue ();
-
+
for ( i = 0 ; i < nArgs ; i++ ) {
args->type = typeFromStr(atypes[i]);
args->etype = getSpec (args->type);
ttree->left = ptree->left;
ptree->left = ttree;
}
-
+
/* Now reverse */
ttree = ptree->left;
ptree->left = ptree->right;
{
RESULT_TYPE resultType;
sym_link *functype;
-
+
/* if none of them exist */
if (!defParm && !*actParm)
return 0;
functype = func->ftype->next;
else
functype = func->ftype;
-
- /* if the function is being called via a pointer & */
- /* it has not been defined a reentrant then we cannot */
- /* have parameters */
+
+ /* 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)
{
if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
{
- werror (W_NONRENT_ARGS);
+ werror (E_NONRENT_ARGS);
fatalError++;
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))
+ /* 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;
if (IS_INTEGRAL (ftype)
&& (getSize (ftype) < (unsigned) INTSIZE))
{
- newType = newAst_LINK(INTTYPE);
+ newType = newAst_LINK(INTTYPE);
}
if (IS_PTR(ftype) && !IS_GENPTR(ftype))
newType = newAst_LINK (copyLinkChain (ftype));
DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
}
-
+
if (newType)
{
/* cast required; change this op to a cast. */
(*actParm)->decorated = 0;
*actParm = newNode (CAST, newType, *actParm);
+ (*actParm)->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;
}
/* 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;
sflds->implicit = 1;
lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
- rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), 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;
if (IS_CHAR (type->next))
if ((rast = createIvalCharPtr (sym,
type,
- decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE))))
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+ rootValue)))
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_TYPE_NONE);
-
- rast = newNode(ARRAYINIT, aSym, NULL);
- rast->values.constlist = literalL;
-
- // Make sure size is set to length of initializer list.
- while (iloop)
- {
- size++;
- iloop = iloop->next;
- }
-
- if (lcnt && size > lcnt)
- {
- // Array size was specified, and we have more initializers than needed.
- char *name=sym->opval.val->sym->name;
- int lineno=sym->opval.val->sym->lineDef;
- char *filename=sym->opval.val->sym->fileDef;
-
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
- }
- }
- 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);
- 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 : "";
- int lineno = iloop->lineno;
- char *filename = iloop->filename;
- 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);
+
+ break;
+ }
+ }
+ }
- /* if we have not been given a size */
- if (!DCL_ELEM (type))
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
{
- /* but this still updates the typedef instead of the instance ! see bug 770487 */
+ /* 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_TYPE_NONE);
+ 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 */
&& 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)
+ unsigned int i = 0;
+ unsigned int symsize = getSize (type);
+
+ size = getSize (iexpr->ftype);
+ if (symsize && size>symsize)
{
if (size>(symsize+1))
- werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
- "string", sym->opval.val->sym->name);
+ {
+ char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+ werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+ "string", name);
+ }
size = symsize;
}
// now WE don't need iexpr's symbol anymore
freeStringSymbol(AST_SYMBOL(iexpr));
+ /* 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);
}
/* 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 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))
/* 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)
SPEC_SCLS (sym->etype) != S_CODE)
{
symbol *newSym;
-
+
/* insert the symbol into the symbol table */
/* with level = 0 & name = rname */
newSym = copySymbol (sym);
} else {
if (getNelements(sym->type, sym->ival)>1) {
werrorfl (sym->fileDef, sym->lineDef,
- W_EXCESS_INITIALIZERS, "scalar",
+ W_EXCESS_INITIALIZERS, "scalar",
sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
list2expr (sym->ival));
}
- setAstLineno (work, sym->lineDef);
+ setAstFileLine (work, sym->fileDef, sym->lineDef);
sym->ival = NULL;
if (staticAutos)
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);
-
+ 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",
+ W_EXCESS_INITIALIZERS, "scalar",
sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (sym)),
list2expr (sym->ival));
}
-
+
// just to be sure
- setAstLineno (work, sym->lineDef);
+ setAstFileLine (work, sym->fileDef, sym->lineDef);
sym->ival = NULL;
if (init)
}
}
}
-
+
/*-----------------------------------------------------------------*/
/* stringToSymbol - creates a symbol from a literal string */
/*-----------------------------------------------------------------*/
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 */
{
*stack += allocVariables (tree->values.sym);
autoInit = gatherAutoInit (tree->values.sym);
-
+
/* if there are auto inits then do them */
if (autoInit)
tree->left = newNode (NULLOP, autoInit, tree->left);
cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
- switch (cexpr->type)
+ switch (cexpr->type)
{
case EX_VALUE:
if (IS_AST_LIT_VALUE(cexpr)) {
// an array's address will never change
return TRUE;
}
- if (IS_AST_SYM_VALUE(cexpr) &&
+ if (IS_AST_SYM_VALUE(cexpr) &&
IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
// a symbol in code space will never change
// This is only for the 'char *s="hallo"' case and will have to leave
// cast ignored, maybe we should throw a warning here?
return constExprTree(cexpr->right);
}
- if (cexpr->opval.op=='&') {
+ if (cexpr->opval.op=='&') {
return TRUE;
}
if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
}
return FALSE;
}
-
+
/*-----------------------------------------------------------------*/
/* constExprValue - returns the value of a constant expression */
/* or NULL if it is not a constant expression */
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)
}
/* 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)
{
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))
{
*end = newNode ('+', condExpr->left->right,
- newAst_VALUE (constVal ("1")));
+ newAst_VALUE (constCharVal (1)));
break;
}
return FALSE;
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)
+ AST_ULONG_VALUE (loopExpr->right) != 1)
return TRUE;
}
}
/*-----------------------------------------------------------------*/
/* astHasVolatile - returns true if ast contains any volatile */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasVolatile (ast * tree)
{
if (!tree)
/*-----------------------------------------------------------------*/
/* astHasPointer - return true if the ast contains any ptr variable */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasPointer (ast * tree)
{
if (!tree)
/*-----------------------------------------------------------------*/
/* astHasSymbol - return true if the ast has the given symbol */
/*-----------------------------------------------------------------*/
-bool
+bool
astHasSymbol (ast * tree, symbol * sym)
{
if (!tree || IS_AST_LINK (tree))
/*-----------------------------------------------------------------*/
/* astHasDeref - return true if the ast has an indirect access */
/*-----------------------------------------------------------------*/
-static bool
+static bool
astHasDeref (ast * tree)
{
if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
return FALSE;
if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
-
+
return astHasDeref (tree->left) || astHasDeref (tree->right);
}
/* isConformingBody - the loop body has to conform to a set of rules */
/* for the loop to be considered reversible read on for rules */
/*-----------------------------------------------------------------*/
-bool
+bool
isConformingBody (ast * pbody, symbol * sym, ast * body)
{
/* if we reach the end or a leaf then true */
if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
return TRUE;
-
+
/* if anything else is "volatile" */
if (IS_VOLATILE (TETYPE (pbody)))
return FALSE;
/*----------------------------*/
case CALL:
/* if local & not passed as paramater then ok */
- if (sym->level && !astHasSymbol(pbody->right,sym))
+ if (sym->level && !astHasSymbol(pbody->right,sym))
return TRUE;
return FALSE;
/* if the for loop is reversible. If yes will set the value of */
/* the loop control var & init value & termination value */
/*-----------------------------------------------------------------*/
-bool
+static bool
isLoopReversible (ast * loop, symbol ** loopCntrl,
ast ** init, ast ** end)
{
/*-----------------------------------------------------------------*/
/* replLoopSym - replace the loop sym by loop sym -1 */
/*-----------------------------------------------------------------*/
-static void
+static void
replLoopSym (ast * body, symbol * sym)
{
/* reached end */
body->type = EX_OP;
body->opval.op = '-';
body->left = newAst_VALUE (symbolVal (sym));
- body->right = newAst_VALUE (constVal ("1"));
+ body->right = newAst_VALUE (constCharVal (1));
}
end));
replLoopSym (loop->left, sym);
- setAstLineno (rloop, init->lineno);
+ setAstFileLine (rloop, init->filename, init->lineno);
rloop = newNode (NULLOP,
newNode ('=',
newNode (NULLOP,
newNode (SUB_ASSIGN,
newAst_VALUE (symbolVal (sym)),
- newAst_VALUE (constVal ("1"))),
+ newAst_VALUE (constCharVal (1))),
rloop))));
rloop->lineno=init->lineno;
/* searchLitOp - search tree (*ops only) for an ast with literal */
/*-----------------------------------------------------------------*/
static ast *
-searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
+searchLitOp (ast *tree, ast **parent, const char *ops)
{
ast *ret;
if (tree->right &&
IS_AST_OP(tree->right) &&
tree->right->right &&
- (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
+ (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)))
if (tree->left &&
IS_AST_OP(tree->left) &&
tree->left->right &&
- (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
+ (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)))
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;
}
{
sym_link *newLink;
bool upCasted = FALSE;
-
+
switch (resultType)
{
case RESULT_TYPE_NONE:
newLink = newIntLink();
upCasted = TRUE;
break;
+ case RESULT_TYPE_IFX:
case RESULT_TYPE_OTHER:
- if (!promote)
- return tree;
- /* return type is long, float: promote char to int */
- if (getSize (tree->etype) >= INTSIZE)
+ if (!promote ||
+ /* return type is ifx, long, float: promote char to int */
+ getSize (tree->etype) >= INTSIZE)
return tree;
newLink = newIntLink();
upCasted = TRUE;
}
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 */
{
case AND_OP:
case OR_OP:
- return resultType;
+ case '!':
case '=':
case '?':
case ':':
case '|':
case '^':
case '~':
+ case LEFT_OP:
+ case LABEL:
+ return resultType;
case '*':
case '+':
case '-':
- case LABEL:
+ 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)
case '[':
if (!IS_ARRAY (LTYPE (tree)))
return resultType;
- if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
+ if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
return RESULT_TYPE_CHAR;
return resultType;
default:
}
}
+/*------------------------------------------------------------------*/
+/* gatherImplicitVariables: assigns correct type information to */
+/* symbols and values created by replaceAstWithTemporary */
+/* and adds the symbols to the declarations list of the */
+/* innermost block that contains them */
+/*------------------------------------------------------------------*/
+void
+gatherImplicitVariables (ast * tree, ast * block)
+{
+ if (!tree)
+ return;
+
+ if (tree->type == EX_OP && tree->opval.op == BLOCK)
+ {
+ /* keep track of containing scope */
+ block = tree;
+ }
+ if (tree->type == EX_OP && tree->opval.op == '=' &&
+ tree->left->type == EX_VALUE && tree->left->opval.val->sym)
+ {
+ symbol *assignee = tree->left->opval.val->sym;
+
+ /* special case for assignment to compiler-generated temporary variable:
+ compute type of RHS, and set the symbol's type to match */
+ if (assignee->type == NULL && assignee->infertype) {
+ ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
+
+ if (dtr != tree->right)
+ tree->right = dtr;
+
+ assignee->type = copyLinkChain(TTYPE(dtr));
+ assignee->etype = getSpec(assignee->type);
+ SPEC_SCLS (assignee->etype) = S_AUTO;
+ SPEC_OCLS (assignee->etype) = NULL;
+ SPEC_EXTR (assignee->etype) = 0;
+ SPEC_STAT (assignee->etype) = 0;
+ SPEC_VOLATILE (assignee->etype) = 0;
+ SPEC_ABSA (assignee->etype) = 0;
+
+ wassertl(block != NULL, "implicit variable not contained in block");
+ wassert(assignee->next == NULL);
+ if (block != NULL) {
+ symbol **decl = &(block->values.sym);
+
+ while (*decl) {
+ wassert(*decl != assignee); /* should not already be in list */
+ decl = &( (*decl)->next );
+ }
+
+ *decl = assignee;
+ }
+ }
+ }
+ if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
+ tree->opval.val->type == NULL &&
+ tree->opval.val->sym &&
+ tree->opval.val->sym->infertype)
+ {
+ /* fixup type of value for compiler-inferred temporary var */
+ tree->opval.val->type = tree->opval.val->sym->type;
+ tree->opval.val->etype = tree->opval.val->sym->etype;
+ }
+
+ gatherImplicitVariables(tree->left, block);
+ gatherImplicitVariables(tree->right, block);
+}
+
/*--------------------------------------------------------------------*/
/* decorateType - compute type for this tree, also does type checking.*/
/* This is done bottom up, since type has to flow upwards. */
-/* resultType flows top-down and forces e.g. char-arithmetik, if the */
+/* resultType flows top-down and forces e.g. char-arithmetic, if the */
/* result is a char and the operand(s) are int's. */
/* It also does constant folding, and parameter checking. */
/*--------------------------------------------------------------------*/
/*----------------------------*/
/* 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 the undefined flag is set then give error message */
if (tree->opval.val->sym->undefined)
{
- werror (E_ID_UNDEF, tree->opval.val->sym->name);
+ 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);
- /* if impilicit i.e. struct/union member then no type */
- if (tree->opval.val->sym->implicit)
- TTYPE (tree) = TETYPE (tree) = NULL;
-
- else
- {
-
- /* else copy the type */
- COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
-
- /* and mark it as referenced */
- tree->opval.val->sym->isref = 1;
- }
+ /* and mark the symbol as referenced */
+ tree->opval.val->sym->isref = 1;
}
}
+ else
+ wassert(0); /* unreached: all values are literals or symbols */
return tree;
}
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);
in tree->left->?type. If the op is e.g. '=' we extract the type
information from there and propagate it to the right branch. */
resultTypeProp = getLeftResultType (tree, resultTypeProp);
-
+
switch (tree->opval.op)
{
case '?':
expansions might rely on this */
dtr = tree->right;
break;
- case CALL:
+ case CALL:
/* decorate right side for CALL (parameter list) in processParms();
there is resultType available */
dtr = tree->right;
break;
- default:
+ 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;
}
/* first check if this is a array or a pointer */
if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
{
- werror (E_NEED_ARRAY_PTR, "[]");
+ 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);
+ 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");
+ 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 arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
int arraySize = DCL_ELEM (LTYPE (tree));
if (arraySize && arrayIndex >= arraySize)
{
- werror (W_IDX_OUT_OF_BOUNDS, 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;
/*------------------------------------------------------------------*/
/* if this is not a structure */
if (!IS_STRUCT (LTYPE (tree)))
{
- werror (E_STRUCT_UNION, ".");
+ werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
goto errorTreeReturn;
}
TTYPE (tree) = structElemType (LTYPE (tree),
/* if not pointer to a structure */
if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
{
- werror (E_PTR_REQD);
+ werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
goto errorTreeReturn;
}
if (!IS_STRUCT (LTYPE (tree)->next))
{
- werror (E_STRUCT_UNION, "->");
+ werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
goto errorTreeReturn;
}
/* adjust the storage class */
switch (DCL_TYPE(tree->left->ftype)) {
case POINTER:
- SPEC_SCLS(TETYPE(tree)) = S_DATA;
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
break;
case FPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+ SPEC_SCLS(TETYPE(tree)) = S_XDATA;
break;
case CPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_CODE;
+ SPEC_SCLS(TETYPE(tree)) = S_CODE;
break;
case GPOINTER:
SPEC_SCLS (TETYPE (tree)) = 0;
break;
case PPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+ SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
break;
case IPOINTER:
SPEC_SCLS(TETYPE(tree)) = S_IDATA;
case FUNCTION:
break;
}
-
+
/* This breaks with extern declarations, bitfields, and perhaps other */
/* cases (gcse). Let's leave this optimization disabled for now and */
/* ponder if there's a safe way to do this. -- EEP */
SPEC_ABSA(sym->etype) = 1;
addSym (SymbolTab, sym, sym->name, 0, 0, 0);
allocGlobal (sym);
-
+
AST_VALUE (tree) = symbolVal(sym);
TLVAL (tree) = 1;
TRVAL (tree) = 0;
tree->right = NULL;
}
#endif
-
+
return tree;
/*------------------------------------------------------------------*/
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;
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
{
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
+ 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);
}
LRVAL (tree) = RRVAL (tree) = 1;
-
+
TTYPE (tree) = computeType (LTYPE (tree),
RTYPE (tree),
resultType,
/* if bit field then error */
if (IS_BITVAR (tree->left->etype))
{
- werror (E_ILLEGAL_ADDR, "address of bit variable");
+ 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");
+ werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
goto errorTreeReturn;
}
if (IS_LITERAL(LTYPE(tree)))
{
- werror (E_ILLEGAL_ADDR, "address of literal");
+ werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
goto errorTreeReturn;
}
if (LRVAL (tree))
{
- werror (E_LVALUE_REQUIRED, "address of");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
goto errorTreeReturn;
}
if (!LETYPE (tree))
/* 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_TYPE_NONE);
-
+
wtree = optimizeSWAP (tree);
if (wtree != tree)
return decorateType (wtree, RESULT_TYPE_NONE);
case '^':
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
{
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
+ 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);
case '/':
if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
{
- werror (E_INVALID_OP, "divide");
+ werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
goto errorTreeReturn;
}
/* if they are both literal then */
/* rearrange the tree */
if (IS_LITERAL (RTYPE (tree))
/* avoid infinite loop */
- && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
+ && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
{
ast *parent;
ast *litTree = searchLitOp (tree, &parent, "/");
litTree->right = newNode ('*',
litTree->right,
copyAst (tree->right));
+ litTree->right->filename = tree->filename;
litTree->right->lineno = tree->lineno;
- tree->right->opval.val = constVal ("1");
+ tree->right->opval.val = constCharVal (1);
decorateType (parent, resultType);
}
else
case '%':
if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
{
- werror (E_BITWISE_OP);
- werror (W_CONTINUE, "left & right types are ");
+ 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);
{
if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
{
- werror (E_PTR_REQD);
+ werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
goto errorTreeReturn;
}
if (LRVAL (tree))
{
- werror (E_LVALUE_REQUIRED, "pointer deref");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
goto errorTreeReturn;
}
if (IS_ADDRESS_OF_OP(tree->left))
SPEC_SCLS(TETYPE(tree)) = S_DATA;
break;
case FPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+ SPEC_SCLS(TETYPE(tree)) = S_XDATA;
break;
case CPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_CODE;
+ SPEC_SCLS(TETYPE(tree)) = S_CODE;
break;
case GPOINTER:
SPEC_SCLS (TETYPE (tree)) = 0;
break;
case PPOINTER:
- SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+ SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
break;
case IPOINTER:
SPEC_SCLS(TETYPE(tree)) = S_IDATA;
/*----------------------------*/
if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
{
- werror (E_INVALID_OP, "multiplication");
+ werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
goto errorTreeReturn;
}
}
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),
{
if (!IS_ARITHMETIC (LTYPE (tree)))
{
- werror (E_UNARY_OP, '+');
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
goto errorTreeReturn;
}
if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
{
- werror (E_PTR_PLUS_PTR);
+ 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, "+");
+ 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, "+");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
goto errorTreeReturn;
}
/* if they are both literal then */
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->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;
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));
}
-
+
return tree;
/*------------------------------------------------------------------*/
if (!IS_ARITHMETIC (LTYPE (tree)))
{
- werror (E_UNARY_OP, tree->opval.op);
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
goto errorTreeReturn;
}
tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
tree->left = NULL;
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- SPEC_USIGN(TETYPE(tree)) = 0;
return tree;
}
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ NULL,
+ resultType,
+ tree->opval.op));
LRVAL (tree) = 1;
- TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
return tree;
}
IS_ARRAY (LTYPE (tree)) ||
IS_ARITHMETIC (LTYPE (tree))))
{
- werror (E_PLUS_INVALID, "-");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
goto errorTreeReturn;
}
IS_ARRAY (RTYPE (tree)) ||
IS_ARITHMETIC (RTYPE (tree))))
{
- werror (E_PLUS_INVALID, "-");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
goto errorTreeReturn;
}
!(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
IS_INTEGRAL (RTYPE (tree))))
{
- werror (E_PLUS_INVALID, "-");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
goto errorTreeReturn;
}
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->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;
{
tree->type = EX_VALUE;
tree->left = tree->right = NULL;
- tree->opval.val = constVal ("0");
+ tree->opval.val = constCharVal (0);
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
return 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),
/* rearrange the tree */
if (IS_LITERAL (RTYPE (tree))
/* avoid infinite loop */
- && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
+ && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
{
ast *litTree, *litParent;
litTree = searchLitOp (tree, &litParent, "+-");
tree->right = litParent->left;
litParent->left = tTree;
litTree->opval.op = '+';
-
+
tree->decorated = 0;
decorateType (tree, resultType);
}
/* can be only integral type */
if (!IS_INTEGRAL (LTYPE (tree)))
{
- werror (E_UNARY_OP, tree->opval.op);
+ werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
goto errorTreeReturn;
}
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 &&
bit -> int -> ~int -> bit
uchar -> int -> ~int -> bit
*/
- werror(W_COMPLEMENT);
+ werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
/* optimize bit-result, even if we optimize a buggy source */
tree->type = EX_VALUE;
- tree->opval.val = constVal ("1");
+ tree->opval.val = constCharVal (1);
}
else
- tree->left = addCast (tree->left, resultType, TRUE);
+ tree->left = addCast (tree->left, resultTypeProp, TRUE);
LRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
return tree;
!IS_PTR (LTYPE (tree)) &&
!IS_ARRAY (LTYPE (tree)))
{
- werror (E_UNARY_OP, tree->opval.op);
+ 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)))
{
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 ");
+ 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);
/* 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)))
/* 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)))) >=
+ ((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))))
{
- lineno=tree->lineno;
- werror (W_SHIFT_CHANGED,
+ 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 = constVal ("0");
+ tree->opval.val = constCharVal (0);
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
return tree;
}
/* cannot cast to an aggregate type */
if (IS_AGGREGATE (LTYPE (tree)))
{
- werror (E_CAST_ILLEGAL);
+ werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
goto errorTreeReturn;
}
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 */
{
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 */ {
+ ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
sym_link *rest = LTYPE(tree)->next;
- werror(W_LITERAL_GENERIC);
+ werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
TTYPE(tree) = newLink(DECLARATOR);
DCL_TYPE(TTYPE(tree)) = FPOINTER;
TTYPE(tree)->next = rest;
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,
+ 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)
+ if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
+ || TARGET_IS_PIC16) )
{
switch (SPEC_SCLS (sym->etype))
{
break;
default:
gptype = 0;
+
+ if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
+ gptype = GPTYPE_NEAR;
}
addr |= gptype << (8*(GPTRSIZE - 1));
}
-
+
tree->type = EX_VALUE;
tree->opval.val =
valCastLiteral (LTYPE (tree), addr);
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;
!IS_ARRAY (LTYPE (tree)) &&
!IS_INTEGRAL (LTYPE (tree)))
{
- werror (E_COMPARE_OP);
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
goto errorTreeReturn;
}
!IS_ARRAY (RTYPE (tree)) &&
!IS_INTEGRAL (RTYPE (tree)))
{
- werror (E_COMPARE_OP);
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
goto errorTreeReturn;
}
/* if they are both literal then */
}
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
- werror (E_COMPARE_OP);
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
fprintf (stderr, "comparing type ");
printTypeChain (LTYPE (tree), stderr);
fprintf (stderr, "to type ");
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
- werror (E_COMPARE_OP);
+ werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
fprintf (stderr, "comparing type ");
printTypeChain (LTYPE (tree), stderr);
fprintf (stderr, "to type ");
goto errorTreeReturn;
}
}
- /* if unsigned value < 0 then always false */
+
+ {
+ CCR_RESULT ccr_result = CCR_OK;
+
+ /* if left is integral and right is literal
+ then check constant range */
+ if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
+ ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
+ tree->opval.op, FALSE);
+ if (ccr_result == CCR_OK &&
+ IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
+ ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
+ tree->opval.op, TRUE);
+ switch (ccr_result)
+ {
+ case CCR_ALWAYS_TRUE:
+ case CCR_ALWAYS_FALSE:
+ if (!options.lessPedantic)
+ 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)
+ ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
{
- if (tree->opval.op == '<')
- {
- return tree->right;
- }
- if (tree->opval.op == '>')
+ if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
{
- if (resultType == RESULT_TYPE_IFX)
- {
- /* the parent is an ifx: */
- /* if (unsigned value) */
- return tree->left;
- }
-
- /* (unsigned value) ? 1 : 0 */
- tree->opval.op = '?';
- tree->right = newNode (':',
- newAst_VALUE (constVal ("1")),
- tree->right); /* val 0 */
- tree->right->lineno = tree->lineno;
- tree->right->left->lineno = tree->lineno;
- decorateType (tree->right, RESULT_TYPE_NONE);
+ /* the parent is an ifx: */
+ /* if (unsigned value) */
+ return tree->left;
}
+
+ /* (unsigned value) ? 1 : 0 */
+ tree->opval.op = '?';
+ tree->right = newNode (':',
+ newAst_VALUE (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)) &&
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;
/*------------------------------------------------------------------*/
/* change the type to a integer */
{
int size = getSize (tree->right->ftype);
+
SNPRINTF(buffer, sizeof(buffer), "%d", size);
if (!size && !IS_VOID(tree->right->ftype))
werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
tree->opval.val->type);
+
return tree;
/*------------------------------------------------------------------*/
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);
+
+ if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
+ ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
{
- tree->right = decorateType (tree->right, resultTypeProp);
- TTYPE (tree) = RTYPE (tree);
- TETYPE (tree) = getSpec (TTYPE (tree));
- }
- return tree;
+ double valTrue = AST_FLOAT_VALUE (tree->right->left);
+ double valFalse = AST_FLOAT_VALUE (tree->right->right);
+
+ if ((valTrue != 0) && (valFalse == 0))
+ {
+ /* assign cond to result */
+ tree->left->decorated = 0;
+ return decorateType (tree->left, resultTypeProp);
+ }
+ else if ((valTrue == 0) && (valFalse != 0))
+ {
+ /* assign !cond to result */
+ tree->opval.op = '!';
+ tree->decorated = 0;
+ tree->right = NULL;
+ return decorateType (tree, resultTypeProp);
+ }
+ else
+ {
+ /* they have the same boolean value, make them equal */
+ tree->right->left = tree->right->right;
+ }
+ }
+
+ /* if they are equal then replace the tree */
+ if (isAstEqual (tree->right->left, tree->right->right))
+ {
+ return tree->right->left;
+ }
+
+ TTYPE (tree) = RTYPE (tree);
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ return tree;
case ':':
/* if they don't match we have a problem */
if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
(compareType (RTYPE (tree), LTYPE (tree)) == 0))
{
- werror (E_TYPE_MISMATCH, "conditional operator", " ");
+ werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
goto errorTreeReturn;
}
if (!IS_ARITHMETIC (LTYPE (tree)) ||
!IS_ARITHMETIC (RTYPE (tree)))
{
- werror (E_OPS_INTEGRAL);
+ 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 ? "*=" : "/=");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
if (!IS_INTEGRAL (LTYPE (tree)) ||
!IS_INTEGRAL (RTYPE (tree)))
{
- werror (E_OPS_INTEGRAL);
+ 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 <<=");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
if (!(IS_PTR (LTYPE (tree)) ||
IS_ARITHMETIC (LTYPE (tree))))
{
- werror (E_PLUS_INVALID, "-=");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
goto errorTreeReturn;
}
if (!(IS_PTR (RTYPE (tree)) ||
IS_ARITHMETIC (RTYPE (tree))))
{
- werror (E_PLUS_INVALID, "-=");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
goto errorTreeReturn;
}
RRVAL (tree) = 1;
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, "-=");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
/* if both pointers then problem */
if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
{
- werror (E_PTR_PLUS_PTR);
+ werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
goto errorTreeReturn;
}
if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
{
- werror (E_PLUS_INVALID, "+=");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
goto errorTreeReturn;
}
if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
{
- werror (E_PLUS_INVALID, "+=");
+ werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
goto errorTreeReturn;
}
RRVAL (tree) = 1;
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, "+=");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
goto errorTreeReturn;
}
/* cannot be an aggregate */
if (IS_AGGREGATE (LTYPE (tree)))
{
- werror (E_AGGR_ASSIGN);
+ 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", " ");
+ werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
printFromToType(RTYPE(tree),LTYPE(tree));
}
then report error */
if (IS_VOID (LTYPE (tree)))
{
- werror (E_CAST_ZERO);
+ werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
printFromToType(RTYPE(tree), LTYPE(tree));
}
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, "=");
+ werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
goto errorTreeReturn;
}
/* function call */
/*----------------------------*/
case CALL:
-
+
/* undo any explicit pointer derefernce; PCALL will handle it instead */
if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
{
if (!tree->right ||
!tree->right->decorated)
{
- sym_link *functype;
+ sym_link *functype;
parmNumber = 1;
if (IS_FUNCPTR (LTYPE (tree)))
- functype = LTYPE (tree)->next;
+ {
+ functype = LTYPE (tree)->next;
+ processFuncPtrArgs (functype);
+ }
else
functype = LTYPE (tree);
{
goto errorTreeReturn;
}
-
- if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
!IFFUNC_ISBUILTIN(functype))
{
reverseParms (tree->right);
if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
{
- werror (W_VOID_FUNC, currFunc->name);
+ werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
goto errorTreeReturn;
}
/*----------------------------*/
case FOR:
- decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
- decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
- decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
+ AST_FOR (tree, initExpr) = decorateType (
+ resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
+ AST_FOR (tree, condExpr) = decorateType (
+ resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
+ AST_FOR (tree, loopExpr) = decorateType (
+ resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
/* if the for loop is reversible then
reverse it otherwise do what we normally
tree->left), RESULT_TYPE_NONE);
}
case PARAM:
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
"node PARAM shouldn't be processed here");
/* but in processParams() */
return tree;
/*-----------------------------------------------------------------*/
/* backPatchLabels - change and or not operators to flow control */
/*-----------------------------------------------------------------*/
-ast *
+static ast *
backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
{
if (!tree)
return NULL;
+ /* while-loops insert a label between the IFX and the condition,
+ therefore look behind the label too */
+ if (tree->opval.op == LABEL &&
+ tree->right &&
+ IS_ANDORNOT (tree->right))
+ {
+ tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
+ return tree;
+ }
+
if (!(IS_ANDORNOT (tree)))
return tree;
/* change not */
if (IS_NOT (tree))
{
- int wasnot = IS_NOT (tree->left);
+ /* call with exchanged labels */
tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
- /* if the left is already a IFX */
+ /* if left isn't already a IFX */
if (!IS_IFX (tree->left))
- tree->left = newNode (IFX, tree->left, NULL);
-
- if (wasnot)
- {
- tree->left->trueLabel = trueLabel;
- tree->left->falseLabel = falseLabel;
- }
- else
{
+ tree->left = newNode (IFX, tree->left, NULL);
tree->left->trueLabel = falseLabel;
tree->left->falseLabel = trueLabel;
}
return tree->left;
- }
+ }
if (IS_IFX (tree))
{
ex = newNode (BLOCK, NULL, body);
ex->values.sym = decl;
-
+
ex->level++;
+ ex->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;
{
/* also order the cases according to value */
value *pval = NULL;
- int cVal = (int) floatFromVal (caseVal->opval.val);
- while (val && (int) floatFromVal (val) < cVal)
+ int cVal = (int) ulFromVal (caseVal->opval.val);
+ while (val && (int) ulFromVal (val) < cVal)
{
pval = val;
val = val->next;
{
pval->next = caseVal->opval.val;
}
- else if ((int) floatFromVal (val) == cVal)
+ else if ((int) ulFromVal (val) == cVal)
{
werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
"case");
}
/* create the case label */
- SNPRINTF(caseLbl, sizeof(caseLbl),
+ SNPRINTF(caseLbl, sizeof(caseLbl),
"_case_%d_%d",
swStat->values.switchVals.swNum,
- (int) floatFromVal (caseVal->opval.val));
+ (int) ulFromVal (caseVal->opval.val));
rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
+ rexpr->filename = 0;
rexpr->lineno = 0;
return rexpr;
}
/* 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));
doTree->trueLabel = continueLabel;
doTree->falseLabel = NULL;
+
+ doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
return doTree;
}
/* 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 */
static int
isBitAndPow2 (ast * tree)
{
- int p2;
-
/* if this is not a bit and */
if (!IS_BITAND (tree))
return -1;
if (!IS_AST_LIT_VALUE (tree->right))
return -1;
- if (AST_LIT_VALUE (tree->right) == 1)
- return 0;
- p2 = powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
- if (!p2)
- return -1;
-
- return p2;
+ return powof2 (AST_ULONG_VALUE (tree->right));
}
/*-----------------------------------------------------------------*/
ast *
optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
{
- int i, j;
+ unsigned int i, j;
ast * expr;
expr = isShiftRightLitVal_BitAndLitVal(tree);
if (expr)
{
- if ((AST_LIT_VALUE (tree->right) != 1) ||
- ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
+ 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) != getSize (TTYPE (expr)) * 8 - 1)
+ if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
expr = NULL;
}
if (!expr)
expr = isShiftRightLitVal_BitAndLitVal(tree);
if (expr)
{
- if (AST_LIT_VALUE (tree->right) != 1)
+ if (AST_ULONG_VALUE (tree->right) != 1)
expr = NULL;
count = tree->left->right;
}
expr = isShiftRightLitVal_BitAndLitVal(tree);
if (expr)
{
- i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+ i = AST_ULONG_VALUE (tree->left->right);
count = tree->left->right;
- if (AST_LIT_VALUE (tree->right) != 0xFF)
+ 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 = (unsigned int) 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))))
expr = isShiftRightLitVal_BitAndLitVal(tree);
if (expr)
{
- i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+ i = AST_ULONG_VALUE (tree->left->right);
count = tree->left->right;
- if (AST_LIT_VALUE (tree->right) != 0xFFFF)
+ 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 = (unsigned int) 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))))
into a RRC operation
note : by 7 I mean (number of bits required to hold the
variable -1 ) */
- /* if the root operations is not a | operation the not */
+ /* if the root operation is not a | operation then not */
if (!IS_BITOR (root))
return root;
/* I have to think of a better way to match patterns this sucks */
- /* that aside let start looking for the first case : I use a the
+ /* that aside let's start looking for the first case : I use a
negative check a lot to improve the efficiency */
/* (?expr << 1) | (?expr >> 7) */
if (IS_LEFT_OP (root->left) &&
root->right->left))
goto tryNext0;
- if (AST_LIT_VALUE (root->left->right) != 1)
+ if (AST_ULONG_VALUE (root->left->right) != 1)
goto tryNext0;
- if (AST_LIT_VALUE (root->right->right) !=
+ if (AST_ULONG_VALUE (root->right->right) !=
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext0;
root->right->left))
goto tryNext1;
- if (AST_LIT_VALUE (root->right->right) != 1)
+ if (AST_ULONG_VALUE (root->right->right) != 1)
goto tryNext1;
- if (AST_LIT_VALUE (root->left->right) !=
+ if (AST_ULONG_VALUE (root->left->right) !=
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext1;
root->right->left))
goto tryNext2;
- if (AST_LIT_VALUE (root->left->right) != 1)
+ if (AST_ULONG_VALUE (root->left->right) != 1)
goto tryNext2;
- if (AST_LIT_VALUE (root->right->right) !=
+ if (AST_ULONG_VALUE (root->right->right) !=
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext2;
root->right->left))
return root;
- if (AST_LIT_VALUE (root->right->right) != 1)
+ if (AST_ULONG_VALUE (root->right->right) != 1)
return root;
- if (AST_LIT_VALUE (root->left->right) !=
+ if (AST_ULONG_VALUE (root->left->right) !=
(getSize (TTYPE (root->left->left)) * 8 - 1))
return root;
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;
root->right->left))
return root;
- if (AST_LIT_VALUE (root->left->right) !=
+ if (AST_ULONG_VALUE (root->left->right) !=
(getSize (TTYPE (root->left->left)) * 4))
return root;
- if (AST_LIT_VALUE (root->right->right) !=
+ if (AST_ULONG_VALUE (root->right->right) !=
(getSize (TTYPE (root->left->left)) * 4))
return root;
case '>':
case '<':
case NE_OP:
- optExpr = newAst_VALUE (constVal ("0"));
+ optExpr = newAst_VALUE (constCharVal (0));
break;
case GE_OP:
case LE_OP:
case EQ_OP:
- optExpr = newAst_VALUE (constVal ("1"));
+ optExpr = newAst_VALUE (constCharVal (1));
break;
}
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)
+ if ((litValue = (int) ulFromVal (vright)) > 1)
{
werror (W_BAD_COMPARE);
goto noOptimize;
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)
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);
addSymChain (&name);
allocVariables (name);
}
- name->lastLine = mylineno;
+ name->lastLine = lexLineno;
currFunc = name;
/* set the stack pointer */
if (IFFUNC_ISREENT (name->type))
reentrant++;
+ 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 */
stackPtr = 0;
xstackPtr = -1;
+ gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
+
/* allocate & autoinit the block variables */
processBlockVars (body, &stack, ALLOCATE);
- /* save the stack information */
- if (options.useXstack)
- name->xstack = SPEC_STAK (fetype) = stack;
- else
- name->stack = SPEC_STAK (fetype) = stack;
-
/* name needs to be mangled */
SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
body = resolveSymbols (body); /* resolve the symbols */
body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
-
+
+ /* save the stack information */
+ if (options.useXstack)
+ name->xstack = SPEC_STAK (fetype) = stack;
+ else
+ name->stack = SPEC_STAK (fetype) = stack;
ex = newAst_VALUE (symbolVal (name)); /* create name */
ex = newNode (FUNCTION, ex, body);
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;
+ 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);
+ if (!tree) return ;
- /*------------------------------------------------------------------*/
- /*----------------------------*/
- /* 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 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) 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 ;
- }
+ /* 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;
}