what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
+#define DEBUG_CF(x) /* puts(x); */
+
#include "common.h"
int currLineno = 0;
int noLineno = 0;
int noAlloc = 0;
-symbol *currFunc;
+symbol *currFunc=NULL;
static ast *createIval (ast *, sym_link *, initList *, ast *);
static ast *createIvalCharPtr (ast *, sym_link *, ast *);
static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
+ast *optimizeSWAP (ast *);
ast *optimizeGetHbit (ast *);
ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
ex = Safe_alloc ( sizeof (ast));
ex->type = type;
- ex->lineno = (noLineno ? oldLineno : yylineno);
+ ex->lineno = (noLineno ? oldLineno : mylineno);
ex->filename = currFname;
ex->level = NestLevel;
ex->block = currBlockno;
ex->initMode = inInitMode;
+ ex->seqPoint = seqPointNo;
return ex;
}
return ex;
}
-ast *
-newAst_STMNT (unsigned val)
-{
- ast *ex = newAst_ (EX_STMNT);
- ex->opval.stmnt = val;
- return ex;
-}
-
/*-----------------------------------------------------------------*/
/* newNode - creates a new node */
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
/* copyAstValues - copies value portion of ast if needed */
/*-----------------------------------------------------------------*/
-void
+void
copyAstValues (ast * dest, ast * src)
{
switch (src->opval.op)
break;
case INLINEASM:
- dest->values.inlineasm = Safe_alloc (strlen (src->values.inlineasm) + 1);
- strcpy (dest->values.inlineasm, src->values.inlineasm);
+ dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
break;
case ARRAYINIT:
dest->values.constlist = copyLiteralList(src->values.constlist);
break;
-
+
case FOR:
AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
/* copyAst - makes a copy of a given astession */
/*-----------------------------------------------------------------*/
ast *
-copyAst (ast * src)
+copyAst (ast * src)
{
ast *dest;
if (!tree)
return NULL;
- if (tree->type == EX_OP &&
+ if (tree->type == EX_OP &&
(tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
if (tree->left)
tree=tree->left;
- else
+ else
tree=tree->right;
}
tree->left=removeIncDecOps(tree->left);
tree->right=removeIncDecOps(tree->right);
-
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePreIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*++s += 3" -> "*++s = *++s + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePreIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->right)
+ tree=tree->right;
+ }
+
+ tree->left=removePreIncDecOps(tree->left);
+ tree->right=removePreIncDecOps(tree->right);
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePostIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*s++ += 3" -> "*s++ = *s++ + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePostIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->left)
+ tree=tree->left;
+ }
+
+ tree->left=removePostIncDecOps(tree->left);
+ tree->right=removePostIncDecOps(tree->right);
+
return tree;
}
/*-----------------------------------------------------------------*/
/* hasSEFcalls - returns TRUE if tree has a function call */
/*-----------------------------------------------------------------*/
-bool
+bool
hasSEFcalls (ast * tree)
{
if (!tree)
/*-----------------------------------------------------------------*/
/* isAstEqual - compares two asts & returns 1 if they are equal */
/*-----------------------------------------------------------------*/
-int
+static int
isAstEqual (ast * t1, ast * t2)
{
if (!t1 && !t2)
if (tree == NULL)
return tree;
+#if 0
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
filename = tree->filename;
lineno = tree->lineno;
}
+#endif
/* make sure we resolve the true & false labels for ifx */
if (tree->type == EX_OP && tree->opval.op == IFX)
tree->trueLabel->name)))
tree->trueLabel = csym;
else
- werror (E_LABEL_UNDEF, tree->trueLabel->name);
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->trueLabel->name);
}
if (tree->falseLabel)
tree->falseLabel->name)))
tree->falseLabel = csym;
else
- werror (E_LABEL_UNDEF, tree->falseLabel->name);
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->falseLabel->name);
}
}
tree->opval.val->sym->name);
if (!csym)
- werror (E_LABEL_UNDEF, tree->opval.val->sym->name);
+ werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+ tree->opval.val->sym->name);
else
tree->opval.val->sym = csym;
/* mark it as returning an int */
if (tree->funcName)
{
- tree->opval.val->sym->type = newLink ();
+ tree->opval.val->sym->type = newLink (DECLARATOR);
DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
tree->opval.val->sym->type->next =
tree->opval.val->sym->etype = newIntLink ();
tree->opval.val->etype = tree->opval.val->etype;
tree->opval.val->type = tree->opval.val->sym->type;
- werror (W_IMPLICIT_FUNC, tree->opval.val->sym->name);
+ werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
+ tree->opval.val->sym->name);
+ //tree->opval.val->sym->undefined = 1;
allocVariables (tree->opval.val->sym);
}
else
sym = newSymbol (name, 0);
/* setup return value */
- sym->type = newLink ();
+ sym->type = newLink (DECLARATOR);
DCL_TYPE (sym->type) = FUNCTION;
sym->type->next = copyLinkChain (type);
sym->etype = getSpec (sym->type);
sym = newSymbol (name, 0);
/* setup return value */
- sym->type = newLink ();
+ sym->type = newLink (DECLARATOR);
DCL_TYPE (sym->type) = FUNCTION;
sym->type->next = typeFromStr(rtype);
sym->etype = getSpec (sym->type);
args = args->next = newValue ();
}
}
-
+
/* save it */
addSymChain (sym);
sym->cdef = 1;
/*-----------------------------------------------------------------*/
/* reverseParms - will reverse a parameter tree */
/*-----------------------------------------------------------------*/
-static void
+static void
reverseParms (ast * ptree)
{
ast *ttree;
/* processParms - makes sure the parameters are okay and do some */
/* processing with them */
/*-----------------------------------------------------------------*/
-int
-processParms (ast * func,
+static int
+processParms (ast *func,
value *defParm,
- ast * actParm,
- int *parmNumber, // unused, although updated
+ ast **actParm,
+ int *parmNumber, /* unused, although updated */
bool rightmost)
{
+ RESULT_TYPE resultType;
+ sym_link *functype;
+
/* if none of them exist */
- if (!defParm && !actParm)
+ if (!defParm && !*actParm)
return 0;
- if (defParm) {
- if (getenv("DEBUG_SANITY")) {
- fprintf (stderr, "processParms: %s ", defParm->name);
+ if (defParm)
+ {
+ if (getenv("DEBUG_SANITY"))
+ {
+ fprintf (stderr, "processParms: %s ", defParm->name);
+ }
+ /* make sure the type is complete and sane */
+ checkTypeSanity(defParm->etype, defParm->name);
}
- /* make sure the type is complete and sane */
- checkTypeSanity(defParm->etype, defParm->name);
- }
+ if (IS_CODEPTR (func->ftype))
+ functype = func->ftype->next;
+ else
+ functype = func->ftype;
+
/* if the function is being called via a pointer & */
/* it has not been defined a reentrant then we cannot */
/* have parameters */
- if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
+ if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
{
werror (W_NONRENT_ARGS);
+ fatalError++;
return 1;
}
/* if defined parameters ended but actual parameters */
/* exist and this is not defined as a variable arg */
- if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
+ if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
{
werror (E_TOO_MANY_PARMS);
return 1;
}
/* if defined parameters present but no actual parameters */
- if (defParm && !actParm)
+ if (defParm && !*actParm)
{
werror (E_TOO_FEW_PARMS);
return 1;
}
- if (IS_VOID(actParm->ftype)) {
- werror (E_VOID_VALUE_USED);
- return 1;
- }
+ /* if this is a PARAM node then match left & right */
+ if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
+ {
+ (*actParm)->decorated = 1;
+ return (processParms (func, defParm,
+ &(*actParm)->left, parmNumber, FALSE) ||
+ processParms (func, defParm ? defParm->next : NULL,
+ &(*actParm)->right, parmNumber, rightmost));
+ }
+ else if (defParm) /* not vararg */
+ {
+ /* If we have found a value node by following only right-hand links,
+ * then we know that there are no more values after us.
+ *
+ * Therefore, if there are more defined parameters, the caller didn't
+ * supply enough.
+ */
+ if (rightmost && defParm->next)
+ {
+ werror (E_TOO_FEW_PARMS);
+ return 1;
+ }
+ }
+
+ /* decorate parameter */
+ resultType = defParm ? getResultTypeFromType (defParm->etype) :
+ RESULT_TYPE_NONE;
+ *actParm = decorateType (*actParm, resultType);
+
+ if (IS_VOID((*actParm)->ftype))
+ {
+ werror (E_VOID_VALUE_USED);
+ return 1;
+ }
/* If this is a varargs function... */
- if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
+ if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
{
ast *newType = NULL;
sym_link *ftype;
- if (IS_CAST_OP (actParm)
- || (IS_AST_LIT_VALUE (actParm) && actParm->values.literalFromCast))
+ if (IS_CAST_OP (*actParm)
+ || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
{
/* Parameter was explicitly typecast; don't touch it. */
return 0;
}
- ftype = actParm->ftype;
-
- /* If it's a small integer, upcast to int. */
+ ftype = (*actParm)->ftype;
+
+ /* If it's a char, upcast to int. */
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. */
- ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
+ ast *parmCopy = resolveSymbols (copyAst (*actParm));
- actParm->type = EX_OP;
- actParm->opval.op = CAST;
- actParm->left = newType;
- actParm->right = parmCopy;
- decorateType (actParm);
- }
- else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
- {
- return (processParms (func, NULL, actParm->left, parmNumber, FALSE) ||
- processParms (func, NULL, actParm->right, parmNumber, rightmost));
+ (*actParm)->type = EX_OP;
+ (*actParm)->opval.op = CAST;
+ (*actParm)->left = newType;
+ (*actParm)->right = parmCopy;
+ (*actParm)->decorated = 0; /* force typechecking */
+ decorateType (*actParm, RESULT_TYPE_NONE);
}
return 0;
- }
+ } /* vararg */
/* if defined parameters ended but actual has not & */
/* reentrant */
- if (!defParm && actParm &&
- (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
+ if (!defParm && *actParm &&
+ (options.stackAuto || IFFUNC_ISREENT (functype)))
return 0;
- resolveSymbols (actParm);
- /* if this is a PARAM node then match left & right */
- if (actParm->type == EX_OP && actParm->opval.op == PARAM)
- {
- return (processParms (func, defParm, actParm->left, parmNumber, FALSE) ||
- processParms (func, defParm->next, actParm->right, parmNumber, rightmost));
- }
- else
+ resolveSymbols (*actParm);
+
+ /* the parameter type must be at least castable */
+ if (compareType (defParm->type, (*actParm)->ftype) == 0)
{
- /* If we have found a value node by following only right-hand links,
- * then we know that there are no more values after us.
- *
- * Therefore, if there are more defined parameters, the caller didn't
- * supply enough.
- */
- if (rightmost && defParm->next)
- {
- werror (E_TOO_FEW_PARMS);
- return 1;
- }
+ werror (E_INCOMPAT_TYPES);
+ printFromToType ((*actParm)->ftype, defParm->type);
+ return 1;
}
- /* the parameter type must be at least castable */
- if (compareType (defParm->type, actParm->ftype) == 0) {
- werror (E_INCOMPAT_TYPES);
- printFromToType (actParm->ftype, defParm->type);
- return 1;
- }
-
/* if the parameter is castable then add the cast */
- if (compareType (defParm->type, actParm->ftype) < 0)
+ if (compareType (defParm->type, (*actParm)->ftype) < 0)
{
- ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
+ ast *pTree;
+ resultType = getResultTypeFromType (defParm->etype);
+ pTree = resolveSymbols (copyAst (*actParm));
+
/* now change the current one to a cast */
- actParm->type = EX_OP;
- actParm->opval.op = CAST;
- actParm->left = newAst_LINK (defParm->type);
- actParm->right = pTree;
- actParm->etype = defParm->etype;
- actParm->ftype = defParm->type;
- actParm->decorated=0; /* force typechecking */
- decorateType (actParm);
+ (*actParm)->type = EX_OP;
+ (*actParm)->opval.op = CAST;
+ (*actParm)->left = newAst_LINK (defParm->type);
+ (*actParm)->right = pTree;
+ (*actParm)->decorated = 0; /* force typechecking */
+ decorateType (*actParm, resultType);
}
/* make a copy and change the regparm type to the defined parm */
- actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
- SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
- SPEC_ARGREG (actParm->etype) = SPEC_ARGREG (defParm->etype);
+ (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
+ SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
+ SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
(*parmNumber)++;
return 0;
}
+
/*-----------------------------------------------------------------*/
/* createIvalType - generates ival for basic types */
/*-----------------------------------------------------------------*/
if (ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iExpr = decorateType (resolveSymbols (list2expr (ilist)));
- return decorateType (newNode ('=', sym, iExpr));
+ iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
+ return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
}
/*-----------------------------------------------------------------*/
break;
sflds->implicit = 1;
lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
- lAst = decorateType (resolveSymbols (lAst));
- rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)));
+ lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
+ rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
}
if (iloop) {
- werror (W_EXCESS_INITIALIZERS, "struct",
- sym->opval.val->sym->name, sym->opval.val->sym->lineDef);
+ werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+ W_EXCESS_INITIALIZERS, "struct",
+ sym->opval.val->sym->name);
}
return rast;
if (IS_CHAR (type->next))
if ((rast = createIvalCharPtr (sym,
type,
- decorateType (resolveSymbols (list2expr (ilist))))))
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
- return decorateType (resolveSymbols (rast));
+ return decorateType (resolveSymbols (rast), RESULT_CHECK);
/* not the special case */
if (ilist->type != INIT_DEEP)
{
ast *aSym;
- aSym = decorateType (resolveSymbols(sym));
+ aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
rast = newNode(ARRAYINIT, aSym, NULL);
rast->values.constlist = literalL;
// 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;
- werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
+ werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
}
}
else
ast *aSym;
aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
- aSym = decorateType (resolveSymbols (aSym));
+ aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
rast = createIval (aSym, type->next, iloop, rast);
iloop = (iloop ? iloop->next : NULL);
if (!iloop)
// there has to be a better way
char *name=sym->opval.val->sym->name;
int lineno=sym->opval.val->sym->lineDef;
- werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
+ char *filename=sym->opval.val->sym->fileDef;
+ werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
break;
}
DCL_ELEM (type) = size;
}
- return decorateType (resolveSymbols (rast));
+ return decorateType (resolveSymbols (rast), RESULT_CHECK);
}
/* to the array element */
char *s = SPEC_CVAL (iexpr->etype).v_char;
int i = 0;
+ int size = getSize (iexpr->ftype);
+ int symsize = getSize (type);
+
+ if (size>symsize)
+ {
+ if (size>(symsize+1))
+ werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+ "string", sym->opval.val->sym->name);
+ size = symsize;
+ }
- while (*s)
+ for (i=0;i<size;i++)
{
rast = newNode (NULLOP,
rast,
newNode ('[', sym,
newAst_VALUE (valueFromLit ((float) i))),
newAst_VALUE (valueFromLit (*s))));
- i++;
s++;
}
- rast = newNode (NULLOP,
- rast,
- newNode ('=',
- newNode ('[', sym,
- newAst_VALUE (valueFromLit ((float) i))),
- newAst_VALUE (valueFromLit (*s))));
- // now we don't need iexpr's symbol anymore
- {
- symbol *sym=AST_SYMBOL(iexpr);
- memmap *segment=SPEC_OCLS(sym->etype);
- deleteSetItem(&segment->syms, sym);
- }
- return decorateType (resolveSymbols (rast));
+ // now WE don't need iexpr's symbol anymore
+ freeStringSymbol(AST_SYMBOL(iexpr));
+
+ return decorateType (resolveSymbols (rast), RESULT_CHECK);
}
return NULL;
if (ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iexpr = decorateType (resolveSymbols (list2expr (ilist)));
+ iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
/* if character pointer */
if (IS_CHAR (type->next))
/* if type is SPECIFIER */
if (IS_SPEC (type))
rast = createIvalType (sym, type, ilist);
-
+
if (wid)
- return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)));
+ return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
else
- return decorateType (resolveSymbols (rast));
+ return decorateType (resolveSymbols (rast), RESULT_CHECK);
}
/*-----------------------------------------------------------------*/
/* resolve the symbols in the ival */
if (sym->ival)
- resolveIvalSym (sym->ival);
+ resolveIvalSym (sym->ival, sym->type);
/* if this is a static variable & has an */
/* initial value the code needs to be lifted */
work = initAggregates (sym, sym->ival, NULL);
} else {
if (getNelements(sym->type, sym->ival)>1) {
- werror (W_EXCESS_INITIALIZERS, "scalar",
- sym->name, sym->lineDef);
+ werrorfl (sym->fileDef, sym->lineDef,
+ W_EXCESS_INITIALIZERS, "scalar",
+ sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
list2expr (sym->ival));
/* if there is an initial value */
if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
{
+ initList *ilist=sym->ival;
+
+ while (ilist->type == INIT_DEEP) {
+ ilist = ilist->init.deep;
+ }
+
+ /* update lineno for error msg */
+ lineno=sym->lineDef;
+ setAstLineno (ilist->init.node, lineno);
+
if (IS_AGGREGATE (sym->type)) {
work = initAggregates (sym, sym->ival, NULL);
} else {
if (getNelements(sym->type, sym->ival)>1) {
- werror (W_EXCESS_INITIALIZERS, "scalar",
- sym->name, sym->lineDef);
+ werrorfl (sym->fileDef, sym->lineDef,
+ W_EXCESS_INITIALIZERS, "scalar",
+ sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (sym)),
list2expr (sym->ival));
}
-
+
+ // just to be sure
setAstLineno (work, sym->lineDef);
+
sym->ival = NULL;
if (init)
init = newNode (NULLOP, init, work);
return init;
}
+/*-----------------------------------------------------------------*/
+/* freeStringSymbol - delete a literal string if no more usage */
+/*-----------------------------------------------------------------*/
+void freeStringSymbol(symbol *sym) {
+ /* make sure this is a literal string */
+ assert (sym->isstrlit);
+ if (--sym->isstrlit == 0) { // lower the usage count
+ memmap *segment=SPEC_OCLS(sym->etype);
+ if (segment) {
+ deleteSetItem(&segment->syms, sym);
+ }
+ }
+}
+
/*-----------------------------------------------------------------*/
/* stringToSymbol - creates a symbol from a literal string */
/*-----------------------------------------------------------------*/
char name[SDCC_NAME_MAX + 1];
static int charLbl = 0;
symbol *sym;
+ set *sp;
+ 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);
+ }
+ }
- sprintf (name, "_str_%d", charLbl++);
+ SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
sym = newSymbol (name, 0); /* make it @ level 0 */
- strcpy (sym->rname, name);
+ strncpyz (sym->rname, name, SDCC_NAME_MAX);
/* copy the type from the value passed */
sym->type = copyLinkChain (val->type);
ast *autoInit;
if (action == ALLOCATE)
- {
+ {
*stack += allocVariables (tree->values.sym);
autoInit = gatherAutoInit (tree->values.sym);
-
+
/* if there are auto inits then do them */
if (autoInit)
tree->left = newNode (NULLOP, autoInit, tree->left);
- }
+ }
else /* action is deallocate */
deallocLocal (tree->values.sym);
}
return tree;
}
+
/*-------------------------------------------------------------*/
/* constExprTree - returns TRUE if this tree is a constant */
/* expression */
return TRUE;
}
- cexpr = decorateType (resolveSymbols (cexpr));
-
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+
switch (cexpr->type)
{
case EX_VALUE:
// a function's address will never change
return TRUE;
}
+ if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
+ // an array's address will never change
+ return TRUE;
+ }
if (IS_AST_SYM_VALUE(cexpr) &&
IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
// a symbol in code space will never change
// This is only for the 'char *s="hallo"' case and will have to leave
+ //printf(" code space symbol");
return TRUE;
}
return FALSE;
return constExprTree(cexpr->right);
}
if (cexpr->opval.op==CAST) {
- // jwk: cast ignored, maybe we should throw a warning here
+ // cast ignored, maybe we should throw a warning here?
return constExprTree(cexpr->right);
}
if (cexpr->opval.op=='&') {
if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
return TRUE;
}
+ return FALSE;
+ case EX_OPERAND:
+ return IS_CONSTANT(operandType(cexpr->opval.oprnd));
}
return FALSE;
-}
+}
/*-----------------------------------------------------------------*/
/* constExprValue - returns the value of a constant expression */
value *
constExprValue (ast * cexpr, int check)
{
- cexpr = decorateType (resolveSymbols (cexpr));
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
/* if this is not a constant then */
if (!IS_LITERAL (cexpr->ftype))
val->sym = cexpr->opval.val->sym;
val->sym->type = copyLinkChain (cexpr->ftype);
val->sym->etype = getSpec (val->sym->type);
- strcpy (val->name, cexpr->opval.val->sym->rname);
+ strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
return val;
}
if (IS_AST_OP (cexpr) &&
cexpr->opval.op == CAST &&
IS_LITERAL (cexpr->right->ftype))
+ {
return valCastLiteral (cexpr->ftype,
floatFromVal (cexpr->right->opval.val));
+ }
if (IS_AST_VALUE (cexpr))
+ {
return cexpr->opval.val;
+ }
if (check)
werror (E_CONST_EXPECTED, "found expression");
else
return FALSE;
}
-
+
return astHasSymbol (tree->left, sym) ||
astHasSymbol (tree->right, sym);
}
return TRUE;
/*------------------------------------------------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP:
case DEC_OP:
/* sure we are not sym is not modified */
case RRC:
case RLC:
case GETHBIT:
+ case SWAP:
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
return FALSE;
case ':':
case SIZEOF: /* evaluate wihout code generation */
+ if (IS_AST_SYM_VALUE (pbody->left) &&
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
+
+ if (IS_AST_SYM_VALUE (pbody->right) &&
+ isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+ return FALSE;
+
return isConformingBody (pbody->left, sym, body) &&
isConformingBody (pbody->right, sym, body);
return FALSE;
// if the loopvar is used in another (maybe conditional) block
if (astHasSymbol (pbody->right, sym) &&
- (pbody->level > body->level)) {
+ (pbody->level >= body->level)) {
return FALSE;
}
}
if (astHasVolatile (pbody->left))
return FALSE;
-
+
if (astHasDeref(pbody->right)) return FALSE;
return isConformingBody (pbody->left, sym, body) &&
/* if the for loop is reversible. If yes will set the value of */
/* the loop control var & init value & termination value */
/*-----------------------------------------------------------------*/
-bool
+bool
isLoopReversible (ast * loop, symbol ** loopCntrl,
ast ** init, ast ** end)
{
newNode ('=',
newAst_VALUE (symbolVal (sym)),
end));
-
+
replLoopSym (loop->left, sym);
setAstLineno (rloop, init->lineno);
-
+
rloop = newNode (NULLOP,
newNode ('=',
newAst_VALUE (symbolVal (sym)),
newAst_VALUE (symbolVal (sym)),
newAst_VALUE (constVal ("1"))),
rloop))));
-
+
rloop->lineno=init->lineno;
- return decorateType (rloop);
+ return decorateType (rloop, RESULT_CHECK);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* searchLitOp - search tree (*ops only) for an ast with literal */
+/*-----------------------------------------------------------------*/
+static ast *
+searchLitOp (ast *tree, ast **parent, const char *ops)
+{
+ ast *ret;
+
+ if (tree && optimize.global_cse)
+ {
+ /* is there a literal operand? */
+ if (tree->right &&
+ IS_AST_OP(tree->right) &&
+ tree->right->right &&
+ (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
+ {
+ if (IS_LITERAL (RTYPE (tree->right)) !=
+ IS_LITERAL (LTYPE (tree->right)))
+ {
+ tree->right->decorated = 0;
+ tree->decorated = 0;
+ *parent = tree;
+ return tree->right;
+ }
+ ret = searchLitOp (tree->right, parent, ops);
+ if (ret)
+ return ret;
+ }
+ if (tree->left &&
+ IS_AST_OP(tree->left) &&
+ tree->left->right &&
+ (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
+ {
+ if (IS_LITERAL (RTYPE (tree->left)) !=
+ IS_LITERAL (LTYPE (tree->left)))
+ {
+ tree->left->decorated = 0;
+ tree->decorated = 0;
+ *parent = tree;
+ return tree->left;
+ }
+ ret = searchLitOp (tree->left, parent, ops);
+ if (ret)
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* getResultFromType */
+/*-----------------------------------------------------------------*/
+RESULT_TYPE
+getResultTypeFromType (sym_link *type)
+{
+ /* type = getSpec (type); */
+ if (IS_BIT (type))
+ return RESULT_TYPE_BIT;
+ if (IS_BITFIELD (type))
+ {
+ int blen = SPEC_BLEN (type);
+
+ if (blen <= 1)
+ return RESULT_TYPE_BIT;
+ if (blen <= 8)
+ return RESULT_TYPE_CHAR;
+ return RESULT_TYPE_INT;
+ }
+ if (IS_CHAR (type))
+ return RESULT_TYPE_CHAR;
+ if ( IS_INT (type)
+ && !IS_LONG (type))
+ return RESULT_TYPE_INT;
+ return RESULT_TYPE_OTHER;
+}
+
+/*-----------------------------------------------------------------*/
+/* addCast - adds casts to a type specified by RESULT_TYPE */
+/*-----------------------------------------------------------------*/
+static ast *
+addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+{
+ sym_link *newLink;
+ bool upCasted = FALSE;
+ switch (resultType)
+ {
+ case RESULT_TYPE_NONE:
+ /* char: promote to int */
+ if (!upcast ||
+ getSize (tree->etype) >= INTSIZE)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ case RESULT_TYPE_CHAR:
+ if (IS_CHAR (tree->etype) ||
+ IS_FLOAT(tree->etype))
+ return tree;
+ newLink = newCharLink();
+ break;
+ case RESULT_TYPE_INT:
+#if 0
+ if (getSize (tree->etype) > INTSIZE)
+ {
+ /* warn ("Loosing significant digits"); */
+ return;
+ }
+#endif
+ /* char: promote to int */
+ if (!upcast ||
+ getSize (tree->etype) >= INTSIZE)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ case RESULT_TYPE_OTHER:
+ if (!upcast)
+ return tree;
+ /* return type is long, float: promote char to int */
+ if (getSize (tree->etype) >= INTSIZE)
+ return tree;
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ default:
+ return tree;
+ }
+ tree->decorated = 0;
+ tree = newNode (CAST, newAst_LINK (newLink), tree);
+ tree->lineno = tree->right->lineno;
+ /* keep unsigned type during cast to smaller type,
+ but not when promoting from char to int */
+ if (!upCasted)
+ SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
+ return decorateType (tree, resultType);
+}
+
+/*-----------------------------------------------------------------*/
+/* resultTypePropagate - decides if resultType can be propagated */
+/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+resultTypePropagate (ast *tree, RESULT_TYPE resultType)
+{
+ switch (tree->opval.op)
+ {
+ case '=':
+ case '?':
+ case ':':
+ case '|':
+ case '^':
+ case '~':
+ case '*':
+ case '+':
+ case '-':
+ case LABEL:
+ return resultType;
+ case '&':
+ if (!tree->right)
+ /* can be unary */
+ return RESULT_TYPE_NONE;
+ else
+ return resultType;
+ case IFX:
+ return RESULT_TYPE_IFX;
+ default:
+ return RESULT_TYPE_NONE;
+ }
}
/*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type cheking */
-/* this is done bottom up, since type have to flow upwards */
-/* it also does constant folding, and paramater checking */
+/* getLeftResultType - gets type from left branch for propagation */
/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+getLeftResultType (ast *tree, RESULT_TYPE resultType)
+{
+ switch (tree->opval.op)
+ {
+ case '=':
+ case CAST:
+ if (IS_PTR (LTYPE (tree)))
+ return RESULT_TYPE_NONE;
+ else
+ return getResultTypeFromType (LETYPE (tree));
+ case RETURN:
+ if (IS_PTR (currFunc->type->next))
+ return RESULT_TYPE_NONE;
+ else
+ return getResultTypeFromType (currFunc->type->next);
+ case '[':
+ if (!IS_ARRAY (LTYPE (tree)))
+ return resultType;
+ if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
+ return RESULT_TYPE_CHAR;
+ return resultType;
+ default:
+ return resultType;
+ }
+}
+
+/*--------------------------------------------------------------------*/
+/* 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 */
+/* result is a char and the operand(s) are int's. */
+/* It also does constant folding, and parameter checking. */
+/*--------------------------------------------------------------------*/
ast *
-decorateType (ast * tree)
+decorateType (ast * tree, RESULT_TYPE resultType)
{
int parmNumber;
sym_link *p;
+ RESULT_TYPE resultTypeProp;
if (!tree)
return tree;
tree->decorated = 1;
+#if 0
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
filename = tree->filename;
lineno = tree->lineno;
}
+#endif
/* if any child is an error | this one is an error do nothing */
if (tree->isError ||
/*------------------------------------------------------------------*/
/*----------------------------*/
- /* leaf has been reached */
+/* leaf has been reached */
/*----------------------------*/
+ lineno=tree->lineno;
/* if this is of type value */
/* just get the type */
if (tree->type == EX_VALUE)
{
ast *dtl, *dtr;
- dtl = decorateType (tree->left);
- /* delay right side for '?' operator since conditional macro expansions might
- rely on this */
- dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right));
+ #if 0
+ if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
+ {
+ if (tree->left && tree->left->type == EX_OPERAND
+ && (tree->left->opval.op == INC_OP
+ || tree->left->opval.op == DEC_OP)
+ && tree->left->left)
+ {
+ tree->left->right = tree->left->left;
+ tree->left->left = NULL;
+ }
+ if (tree->right && tree->right->type == EX_OPERAND
+ && (tree->right->opval.op == INC_OP
+ || tree->right->opval.op == DEC_OP)
+ && tree->right->left)
+ {
+ tree->right->right = tree->right->left;
+ tree->right->left = NULL;
+ }
+ }
+ #endif
+
+ /* Before decorating the left branch we've to decide in dependence
+ upon tree->opval.op, if resultType can be propagated */
+ resultTypeProp = resultTypePropagate (tree, resultType);
+
+ if (tree->opval.op == '?')
+ dtl = decorateType (tree->left, RESULT_TYPE_IFX);
+ else
+ dtl = decorateType (tree->left, resultTypeProp);
+
+ /* if an array node, we may need to swap branches */
+ if (tree->opval.op == '[')
+ {
+ /* determine which is the array & which the index */
+ if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
+ IS_INTEGRAL (LTYPE (tree)))
+ {
+ ast *tempTree = tree->left;
+ tree->left = tree->right;
+ tree->right = tempTree;
+ }
+ }
+
+ /* After decorating the left branch there's type information available
+ in tree->left->?type. If the op is e.g. '=' we extract the type
+ information from there and propagate it to the right branch. */
+ resultTypeProp = getLeftResultType (tree, resultTypeProp);
+
+ switch (tree->opval.op)
+ {
+ case '?':
+ /* delay right side for '?' operator since conditional macro
+ expansions might rely on this */
+ dtr = tree->right;
+ break;
+ case CALL:
+ /* decorate right side for CALL (parameter list) in processParms();
+ there is resultType available */
+ dtr = tree->right;
+ break;
+ default:
+ dtr = decorateType (tree->right, resultTypeProp);
+ break;
+ }
/* this is to take care of situations
when the tree gets rewritten */
tree->left = dtl;
if (dtr != tree->right)
tree->right = dtr;
+ if ((dtl && dtl->isError) || (dtr && dtr->isError))
+ return tree;
}
/* depending on type of operator do */
/*----------------------------*/
case '[':
- /* determine which is the array & which the index */
- if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree)))
- {
-
- ast *tempTree = tree->left;
- tree->left = tree->right;
- tree->right = tempTree;
- }
-
/* first check if this is a array or a pointer */
if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
{
werror (E_LVALUE_REQUIRED, "array access");
goto errorTreeReturn;
}
+
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
+ int arraySize = DCL_ELEM (LTYPE (tree));
+ if (arraySize && arrayIndex >= arraySize)
+ {
+ werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
+ }
+ }
+
RRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
- if (IS_PTR(LTYPE(tree))) {
- SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree));
- }
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
case PTR_OP:
/* if not pointer to a structure */
- if (!IS_PTR (LTYPE (tree)))
+ if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
{
werror (E_PTR_REQD);
goto errorTreeReturn;
/* adjust the storage class */
switch (DCL_TYPE(tree->left->ftype)) {
case POINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
break;
case FPOINTER:
SPEC_SCLS(TETYPE(tree)) = S_XDATA;
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_EEPROM;
break;
case UPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
case ARRAY:
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 */
+ #if 0
+ if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
+ && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
+ {
+ /* If defined struct type at addr var
+ then rewrite (&struct var)->member
+ as temp
+ and define membertype at (addr+offsetof(struct var,member)) temp
+ */
+ symbol *sym;
+ symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
+ AST_SYMBOL(tree->right));
+
+ sym = newSymbol(genSymName (0), 0);
+ sym->type = TTYPE (tree);
+ sym->etype = getSpec(sym->type);
+ sym->lineDef = tree->lineno;
+ sym->cdef = 1;
+ sym->isref = 1;
+ SPEC_STAT (sym->etype) = 1;
+ SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
+ + element->offset;
+ 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->type = EX_VALUE;
+ tree->left = NULL;
+ tree->right = NULL;
+ }
+ #endif
+
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP:
case DEC_OP:
{
sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
- if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
- werror (E_CODE_WRITE, "++/--");
+ if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
+ werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
if (tree->right)
RLVAL (tree) = 1;
ast *otree = optimizeGetHbit (tree);
if (otree != tree)
- return decorateType (otree);
+ return decorateType (otree, RESULT_CHECK);
}
- TTYPE (tree) =
- computeType (LTYPE (tree), RTYPE (tree));
+ TTYPE (tree) = computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op);
TETYPE (tree) = getSpec (TTYPE (tree));
+ /* if left is a literal exchange left & right */
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ ast *tTree = tree->left;
+ tree->left = tree->right;
+ tree->right = tTree;
+ }
+
+ /* if right is a literal and */
+ /* we can find a 2nd literal in a and-tree then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "&");
+ if (litTree)
+ {
+ DEBUG_CF("&")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in tTree are literal now */
+ decorateType (parent, resultType);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
+
return tree;
}
/*----------------------------*/
/* address of */
/*----------------------------*/
- p = newLink ();
- p->class = DECLARATOR;
+ p = newLink (DECLARATOR);
/* if bit field then error */
if (IS_BITVAR (tree->left->etype))
{
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_REGISTER)
+ if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
{
werror (E_ILLEGAL_ADDR, "address of register variable");
goto errorTreeReturn;
werror (E_LVALUE_REQUIRED, "address of");
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_CODE)
- {
- DCL_TYPE (p) = CPOINTER;
- DCL_PTR_CONST (p) = port->mem.code_ro;
- }
+ if (!LETYPE (tree))
+ DCL_TYPE (p) = POINTER;
+ else if (SPEC_SCLS (tree->left->etype) == S_CODE)
+ DCL_TYPE (p) = CPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
DCL_TYPE (p) = FPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
p->next = LTYPE (tree);
TTYPE (tree) = p;
TETYPE (tree) = getSpec (TTYPE (tree));
- DCL_PTR_CONST (p) = SPEC_CONST (TETYPE (tree));
- DCL_PTR_VOLATILE (p) = SPEC_VOLATILE (TETYPE (tree));
LLVAL (tree) = 1;
TLVAL (tree) = 1;
+
+ #if 0
+ if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
+ && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
+ {
+ symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
+ AST_SYMBOL(tree->left->right));
+ AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
+ valueFromLit(element->offset));
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->type = EX_VALUE;
+ tree->values.literalFromCast = 1;
+ }
+ #endif
+
return tree;
/*------------------------------------------------------------------*/
{
ast *wtree = optimizeRRCRLC (tree);
if (wtree != tree)
- return decorateType (wtree);
+ return decorateType (wtree, RESULT_CHECK);
+
+ wtree = optimizeSWAP (tree);
+ if (wtree != tree)
+ return decorateType (wtree, RESULT_CHECK);
}
+
+ /* if left is a literal exchange left & right */
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ ast *tTree = tree->left;
+ tree->left = tree->right;
+ tree->right = tTree;
+ }
+
+ /* if right is a literal and */
+ /* we can find a 2nd literal in a or-tree then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "|");
+ if (litTree)
+ {
+ DEBUG_CF("|")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in tTree are literal now */
+ decorateType (parent, resultType);
+ }
+ }
+ /* fall through */
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* bitwise xor */
TTYPE (tree) = tree->opval.val->type;
return tree;
}
+
+ /* if left is a literal exchange left & right */
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ ast *tTree = tree->left;
+ tree->left = tree->right;
+ tree->right = tTree;
+ }
+
+ /* if right is a literal and */
+ /* we can find a 2nd literal in a xor-tree then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)) &&
+ tree->opval.op == '^') /* the same source is used by 'bitwise or' */
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "^");
+ if (litTree)
+ {
+ DEBUG_CF("^")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in litTree are literal now */
+ decorateType (parent, resultType);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+
+ return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
tree->opval.val->type);
return tree;
}
+
LRVAL (tree) = RRVAL (tree) = 1;
+
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+
+ /* if right is a literal and */
+ /* left is also a division by a literal then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree))
+ /* avoid infinite loop */
+ && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "/");
+ if (litTree)
+ {
+ if (IS_LITERAL (RTYPE (litTree)))
+ {
+ /* foo_div */
+ DEBUG_CF("div r")
+ litTree->right = newNode ('*',
+ litTree->right,
+ copyAst (tree->right));
+ litTree->right->lineno = tree->lineno;
+
+ tree->right->opval.val = constVal ("1");
+ decorateType (parent, resultType);
+ }
+ else
+ {
+ /* litTree->left is literal: no gcse possible.
+ We can't call decorateType(parent, RESULT_CHECK), because
+ this would cause an infinit loop. */
+ parent->decorated = 1;
+ decorateType (litTree, resultType);
+ }
+ }
+ }
+
return tree;
/*------------------------------------------------------------------*/
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
return tree;
/*------------------------------------------------------------------*/
werror (E_LVALUE_REQUIRED, "pointer deref");
goto errorTreeReturn;
}
- TTYPE (tree) = copyLinkChain ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) ?
- LTYPE (tree)->next : NULL);
- TETYPE (tree) = getSpec (TTYPE (tree));
- SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree));
+ if (IS_ADDRESS_OF_OP(tree->left))
+ {
+ /* replace *&obj with obj */
+ return tree->left->left;
+ }
+ TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ /* adjust the storage class */
+ switch (DCL_TYPE(tree->left->ftype)) {
+ case POINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
+ break;
+ case FPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+ break;
+ case CPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_CODE;
+ break;
+ case GPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
+ case PPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+ break;
+ case IPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+ break;
+ case EEPPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
+ break;
+ case UPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
+ case ARRAY:
+ case FUNCTION:
+ break;
+ }
return tree;
}
tree->right = tTree;
}
+ /* if right is a literal and */
+ /* we can find a 2nd literal in a mul-tree then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ ast *parent;
+ ast *litTree = searchLitOp (tree, &parent, "*");
+ if (litTree)
+ {
+ DEBUG_CF("mul")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ /* both operands in litTree are literal now */
+ decorateType (parent, resultType);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
- /* promote result to int if left & right are char
- this will facilitate hardware multiplies 8bit x 8bit = 16bit */
- if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree)));
- SPEC_NOUN(TETYPE(tree)) = V_INT;
- } else {
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree)));
- }
+ tree->left = addCast (tree->left, resultType, FALSE);
+ tree->right = addCast (tree->right, resultType, FALSE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+
return tree;
/*------------------------------------------------------------------*/
/* if unary plus */
if (!tree->right)
{
- if (!IS_INTEGRAL (LTYPE (tree)))
+ if (!IS_ARITHMETIC (LTYPE (tree)))
{
werror (E_UNARY_OP, '+');
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->opval.val = valPlus (valFromType (LETYPE (tree)),
valFromType (RETYPE (tree)));
tree->right = tree->left = NULL;
tree->right = tTree;
}
+ /* if right is a literal and */
+ /* left is also an addition/subtraction with a literal then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree)))
+ {
+ ast *litTree, *parent;
+ litTree = searchLitOp (tree, &parent, "+-");
+ if (litTree)
+ {
+ if (litTree->opval.op == '+')
+ {
+ /* foo_aa */
+ DEBUG_CF("+ 1 AA")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tree->left;
+ tree->left = tTree;
+ }
+ else if (litTree->opval.op == '-')
+ {
+ if (IS_LITERAL (RTYPE (litTree)))
+ {
+ DEBUG_CF("+ 2 ASR")
+ /* foo_asr */
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = tTree;
+ }
+ else
+ {
+ DEBUG_CF("+ 3 ASL")
+ /* foo_asl */
+ ast *tTree = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ litTree->opval.op = '+';
+ tree->opval.op = '-';
+ }
+ }
+ decorateType (parent, resultType);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
/* if the left is a pointer */
- if (IS_PTR (LTYPE (tree)))
+ if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
TETYPE (tree) = getSpec (TTYPE (tree) =
LTYPE (tree));
else
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree)));
+ {
+ tree->left = addCast (tree->left, resultType, TRUE);
+ tree->right = addCast (tree->right, resultType, TRUE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+ }
+
return tree;
/*------------------------------------------------------------------*/
return tree;
}
LRVAL (tree) = 1;
- TTYPE (tree) = LTYPE (tree);
+ TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
return tree;
}
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
{
tree->type = EX_VALUE;
+ tree->left = addCast (tree->left, resultType, TRUE);
+ tree->right = addCast (tree->right, resultType, TRUE);
tree->opval.val = valMinus (valFromType (LETYPE (tree)),
valFromType (RETYPE (tree)));
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
LTYPE (tree));
else
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree)));
+ {
+ tree->left = addCast (tree->left, resultType, TRUE);
+ tree->right = addCast (tree->right, resultType, TRUE);
+
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
+
+ /* if right is a literal and */
+ /* left is also an addition/subtraction with a literal then */
+ /* rearrange the tree */
+ if (IS_LITERAL (RTYPE (tree))
+ /* avoid infinite loop */
+ && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
+ {
+ ast *litTree, *litParent;
+ litTree = searchLitOp (tree, &litParent, "+-");
+ if (litTree)
+ {
+ if (litTree->opval.op == '+')
+ {
+ /* foo_sa */
+ DEBUG_CF("- 1 SA")
+ ast *tTree = litTree->left;
+ litTree->left = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ tree->opval.op = '+';
+ litTree->opval.op = '-';
+ }
+ else if (litTree->opval.op == '-')
+ {
+ if (IS_LITERAL (RTYPE (litTree)))
+ {
+ /* foo_ssr */
+ DEBUG_CF("- 2 SSR")
+ ast *tTree = litTree->left;
+ litTree->left = tree->right;
+ tree->right = litParent->left;
+ litParent->left = tTree;
+ litTree->opval.op = '+';
+
+ tree->decorated = 0;
+ decorateType (tree, resultType);
+ }
+ else
+ {
+ /* foo_ssl */
+ DEBUG_CF("- 3 SSL")
+ ast *tTree = litTree->right;
+ litTree->right = tree->right;
+ tree->right = tTree;
+ }
+ }
+ decorateType (litParent, resultType);
+ }
+ }
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
- /* compliment */
+ /* complement */
/*----------------------------*/
case '~':
/* can be only integral type */
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
return tree;
}
+ tree->left = addCast (tree->left, resultType, TRUE);
LRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
return tree;
/*----------------------------*/
case RRC:
case RLC:
+ case SWAP:
TTYPE (tree) = LTYPE (tree);
TETYPE (tree) = LETYPE (tree);
return tree;
goto errorTreeReturn;
}
+ /* make smaller type only if it's a LEFT_OP */
+ if (tree->opval.op == LEFT_OP)
+ tree->left = addCast (tree->left, resultType, TRUE);
+
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
tree->opval.val->type);
return tree;
}
- /* a left shift must be done with at least 16bits */
- if ((tree->opval.op==LEFT_OP) && (getSize(LTYPE(tree))<2)) {
- // insert a cast
- if (IS_AST_SYM_VALUE(tree->left)) {
- tree->left =
- decorateType (newNode (CAST,
- newAst_LINK(copyLinkChain(LTYPE(tree))),
- tree->left));
- SPEC_NOUN(tree->left->left->ftype)=V_INT;
- } else {
- // must be a literal, we can do it right away
- SPEC_NOUN(tree->left->opval.val->type)=V_INT;
- }
- }
- /* if only the right side is a literal & we are
- shifting more than size of the left operand then zero */
- if (IS_LITERAL (RTYPE (tree)) &&
- ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
- (getSize (LTYPE (tree)) * 8))
+
+ LRVAL (tree) = RRVAL (tree) = 1;
+ if (tree->opval.op == LEFT_OP)
{
- werror (W_SHIFT_CHANGED,
- (tree->opval.op == LEFT_OP ? "left" : "right"));
- tree->type = EX_VALUE;
- tree->left = tree->right = NULL;
- tree->opval.val = constVal ("0");
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ NULL,
+ resultType,
+ tree->opval.op));
}
- LRVAL (tree) = RRVAL (tree) = 1;
- if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree)))
+ else /* RIGHT_OP */
{
- COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree));
+ /* no promotion necessary */
+ TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+ if (IS_LITERAL (TTYPE (tree)))
+ SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
}
- else
+
+ /* if only the right side is a literal & we are
+ shifting more than size of the left operand then zero */
+ if (IS_LITERAL (RTYPE (tree)) &&
+ ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
+ (getSize (TETYPE (tree)) * 8))
{
- COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
+ if (tree->opval.op==LEFT_OP ||
+ (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
+ {
+ lineno=tree->lineno;
+ werror (W_SHIFT_CHANGED,
+ (tree->opval.op == LEFT_OP ? "left" : "right"));
+ tree->type = EX_VALUE;
+ tree->left = tree->right = NULL;
+ tree->opval.val = constVal ("0");
+ TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+ return tree;
+ }
}
+
return tree;
/*------------------------------------------------------------------*/
werror (E_CAST_ILLEGAL);
goto errorTreeReturn;
}
-
+
/* make sure the type is complete and sane */
checkTypeSanity(LETYPE(tree), "(cast)");
+ /* If code memory is read only, then pointers to code memory */
+ /* implicitly point to constants -- make this explicit */
+ {
+ sym_link *t = LTYPE(tree);
+ while (t && t->next)
+ {
+ if (IS_CODEPTR(t) && port->mem.code_ro)
+ {
+ if (IS_SPEC(t->next))
+ SPEC_CONST (t->next) = 1;
+ else
+ DCL_PTR_CONST (t->next) = 1;
+ }
+ t = t->next;
+ }
+ }
+
#if 0
/* if the right is a literal replace the tree */
if (IS_LITERAL (RETYPE (tree))) {
tree->right = NULL;
TTYPE (tree) = tree->opval.val->type;
tree->values.literalFromCast = 1;
- } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
+ } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
sym_link *rest = LTYPE(tree)->next;
- werror(W_LITERAL_GENERIC);
- TTYPE(tree) = newLink();
+ werror(W_LITERAL_GENERIC);
+ TTYPE(tree) = newLink(DECLARATOR);
DCL_TYPE(TTYPE(tree)) = FPOINTER;
TTYPE(tree)->next = rest;
tree->left->opval.lnk = TTYPE(tree);
/* if pointer to struct then check names */
if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
- strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
+ strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
{
werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
SPEC_STRUCT(LETYPE(tree))->tag);
}
#endif
- /* if the right is a literal replace the tree */
- if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree))) {
- tree->type = EX_VALUE;
+ if (IS_ADDRESS_OF_OP(tree->right)
+ && IS_AST_SYM_VALUE (tree->right->left)
+ && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
+
+ tree->type = EX_VALUE;
tree->opval.val =
valCastLiteral (LTYPE (tree),
- floatFromVal (valFromType (RETYPE (tree))));
+ SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
+ TTYPE (tree) = tree->opval.val->type;
+ TETYPE (tree) = getSpec (TTYPE (tree));
tree->left = NULL;
tree->right = NULL;
- TTYPE (tree) = tree->opval.val->type;
tree->values.literalFromCast = 1;
- } else {
- TTYPE (tree) = LTYPE (tree);
- LRVAL (tree) = 1;
+ return tree;
+ }
+
+ /* handle offsetof macro: */
+ /* #define offsetof(TYPE, MEMBER) \ */
+ /* ((unsigned) &((TYPE *)0)->MEMBER) */
+ if (IS_ADDRESS_OF_OP(tree->right)
+ && IS_AST_OP (tree->right->left)
+ && tree->right->left->opval.op == PTR_OP
+ && IS_AST_OP (tree->right->left->left)
+ && tree->right->left->left->opval.op == CAST
+ && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
+
+ symbol *element = getStructElement (
+ SPEC_STRUCT (LETYPE(tree->right->left)),
+ AST_SYMBOL(tree->right->left->right)
+ );
+
+ if (element) {
+ tree->type = EX_VALUE;
+ tree->opval.val = valCastLiteral (
+ LTYPE (tree),
+ element->offset
+ + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
+ );
+
+ TTYPE (tree) = tree->opval.val->type;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ tree->left = NULL;
+ tree->right = NULL;
+ return tree;
+ }
+ }
+
+ /* if the right is a literal replace the tree */
+ if (IS_LITERAL (RETYPE (tree))) {
+ #if 0
+ if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
+ /* rewrite (type *)litaddr
+ as &temp
+ and define type at litaddr temp
+ (but only if type's storage class is not generic)
+ */
+ ast *newTree = newNode ('&', NULL, NULL);
+ symbol *sym;
+
+ TTYPE (newTree) = LTYPE (tree);
+ TETYPE (newTree) = getSpec(LTYPE (tree));
+
+ /* define a global symbol at the casted address*/
+ sym = newSymbol(genSymName (0), 0);
+ sym->type = LTYPE (tree)->next;
+ if (!sym->type)
+ sym->type = newLink (V_VOID);
+ sym->etype = getSpec(sym->type);
+ SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
+ sym->lineDef = tree->lineno;
+ sym->cdef = 1;
+ sym->isref = 1;
+ SPEC_STAT (sym->etype) = 1;
+ SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
+ SPEC_ABSA(sym->etype) = 1;
+ addSym (SymbolTab, sym, sym->name, 0, 0, 0);
+ allocGlobal (sym);
+
+ newTree->left = newAst_VALUE(symbolVal(sym));
+ newTree->left->lineno = tree->lineno;
+ LTYPE (newTree) = sym->type;
+ LETYPE (newTree) = sym->etype;
+ LLVAL (newTree) = 1;
+ LRVAL (newTree) = 0;
+ TLVAL (newTree) = 1;
+ return newTree;
+ }
+ #endif
+ if (!IS_PTR (LTYPE (tree))) {
+ tree->type = EX_VALUE;
+ tree->opval.val =
+ valCastLiteral (LTYPE (tree),
+ floatFromVal (valFromType (RTYPE (tree))));
+ TTYPE (tree) = tree->opval.val->type;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->values.literalFromCast = 1;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ return tree;
+ }
}
-#endif
+ TTYPE (tree) = LTYPE (tree);
+ LRVAL (tree) = 1;
+
+#endif
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
/*----------------------------*/
case AND_OP:
case OR_OP:
- /* each must me arithmetic type or be a pointer */
+ /* each must be arithmetic type or be a pointer */
if (!IS_PTR (LTYPE (tree)) &&
!IS_ARRAY (LTYPE (tree)) &&
!IS_INTEGRAL (LTYPE (tree)))
IS_LITERAL (LTYPE (tree)))
{
tree->type = EX_VALUE;
- tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
+ tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+ valFromType (RTYPE (tree)),
tree->opval.op);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
/* if they are pointers they must be castable */
if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
{
+ if (tree->opval.op==EQ_OP &&
+ !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
+ // we cannot cast a gptr to a !gptr: switch the leaves
+ struct ast *s=tree->left;
+ tree->left=tree->right;
+ tree->right=s;
+ }
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
werror (E_COMPARE_OP);
}
}
/* if unsigned value < 0 then always false */
- /* if (unsigned value) > 0 then (unsigned value) */
- if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) &&
- ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) {
-
- if (tree->opval.op == '<') {
+ /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
+ if (SPEC_USIGN(LETYPE(tree)) &&
+ !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
+ IS_LITERAL(RTYPE(tree)) &&
+ ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
+ {
+ if (tree->opval.op == '<')
+ {
return tree->right;
- }
- if (tree->opval.op == '>') {
- return tree->left;
- }
- }
+ }
+ if (tree->opval.op == '>')
+ {
+ if (resultType == RESULT_TYPE_IFX)
+ {
+ /* the parent is an ifx: */
+ /* if (unsigned value) */
+ return tree->left;
+ }
+
+ /* (unsigned value) ? 1 : 0 */
+ tree->opval.op = '?';
+ tree->right = newNode (':',
+ newAst_VALUE (constVal ("1")),
+ tree->right); /* val 0 */
+ tree->right->lineno = tree->lineno;
+ tree->right->left->lineno = tree->lineno;
+ decorateType (tree->right, RESULT_CHECK);
+ }
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (tree)) &&
/*----------------------------*/
case SIZEOF: /* evaluate wihout code generation */
/* change the type to a integer */
+ {
+ int size = getSize (tree->right->ftype);
+ SNPRINTF(buffer, sizeof(buffer), "%d", size);
+ if (!size && !IS_VOID(tree->right->ftype))
+ werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
+ }
tree->type = EX_VALUE;
- sprintf (buffer, "%d", (getSize (tree->right->ftype)));
tree->opval.val = constVal (buffer);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
case V_STRUCT:
typeofv = TYPEOF_STRUCT;
break;
+ case V_BITFIELD:
+ typeofv = TYPEOF_BITFIELD;
+ break;
case V_BIT:
typeofv = TYPEOF_BIT;
break;
break;
}
}
- sprintf (buffer, "%d", typeofv);
+ SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
tree->opval.val = constVal (buffer);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
/*----------------------------*/
case '?':
/* the type is value of the colon operator (on the right) */
- assert(IS_COLON_OP(tree->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 (IS_LITERAL (LTYPE(tree))) {
- if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
- return decorateType(tree->right->left) ;
- } else {
- return decorateType(tree->right->right) ;
- }
- } else {
- tree->right = decorateType(tree->right);
- TTYPE (tree) = RTYPE(tree);
+ if (IS_LITERAL (LTYPE (tree)))
+ {
+ if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
+ return decorateType (tree->right->left, resultTypeProp);
+ else
+ return decorateType (tree->right->right, resultTypeProp);
+ }
+ else
+ {
+ tree->right = decorateType (tree->right, resultTypeProp);
+ TTYPE (tree) = RTYPE (tree);
TETYPE (tree) = getSpec (TTYPE (tree));
- }
+ }
return tree;
case ':':
goto errorTreeReturn;
}
- TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree));
+ TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+ resultType, tree->opval.op);
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
- if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, " ");
+ if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
+ werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
if (LRVAL (tree))
{
- werror (E_LVALUE_REQUIRED, "*= or /=");
+ werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, " ");
+ werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
if (LRVAL (tree))
{
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, " ");
+ werror (E_CODE_WRITE, "-=");
if (LRVAL (tree))
{
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
- werror (E_CODE_WRITE, " ");
+ werror (E_CODE_WRITE, "+=");
if (LRVAL (tree))
{
goto errorTreeReturn;
}
- tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
+ tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
tree->opval.op = '=';
return tree;
{
werror (E_TYPE_MISMATCH, "assignment", " ");
printFromToType(RTYPE(tree),LTYPE(tree));
- //goto errorTreeReturn;
}
/* if the left side of the tree is of type void
RRVAL (tree) = 1;
LLVAL (tree) = 1;
if (!tree->initMode ) {
- if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree))))
- werror (E_CODE_WRITE, " ");
+ if (IS_CONSTANT(LTYPE(tree)))
+ werror (E_CODE_WRITE, "=");
}
if (LRVAL (tree))
{
/* function call */
/*----------------------------*/
case CALL:
- parmNumber = 1;
-
- if (processParms (tree->left,
- FUNC_ARGS(tree->left->ftype),
- tree->right, &parmNumber, TRUE)) {
- goto errorTreeReturn;
- }
+
+ /* undo any explicit pointer derefernce; PCALL will handle it instead */
+ if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
+ {
+ if (tree->left->opval.op == '*' && !tree->left->right)
+ tree->left = tree->left->left;
+ }
- if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) &&
- !IFFUNC_ISBUILTIN(LTYPE(tree)))
+ /* require a function or pointer to function */
+ if (!IS_FUNC (LTYPE (tree))
+ && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
{
- //FUNC_ARGS(tree->left->ftype) =
- //reverseVal (FUNC_ARGS(tree->left->ftype));
- reverseParms (tree->right);
+ werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+ goto errorTreeReturn;
}
- TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)->next);
+ {
+ sym_link *functype;
+ parmNumber = 1;
+
+ if (IS_CODEPTR(LTYPE(tree)))
+ functype = LTYPE (tree)->next;
+ else
+ functype = LTYPE (tree);
+
+ if (processParms (tree->left, FUNC_ARGS(functype),
+ &tree->right, &parmNumber, TRUE)) {
+ goto errorTreeReturn;
+ }
+
+ if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+ !IFFUNC_ISBUILTIN(functype))
+ {
+ reverseParms (tree->right);
+ }
+
+ TTYPE (tree) = functype->next;
+ TETYPE (tree) = getSpec (TTYPE (tree));
+ }
return tree;
/*------------------------------------------------------------------*/
if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
{
- werror (W_RETURN_MISMATCH);
+ werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
printFromToType (RTYPE(tree), currFunc->type->next);
goto errorTreeReturn;
}
&& tree->right &&
!IS_VOID (RTYPE (tree)))
{
- werror (E_FUNC_VOID);
+ werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
goto errorTreeReturn;
}
- /* if there is going to be a casing required then add it */
+ /* if there is going to be a casting required then add it */
if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
{
tree->right =
decorateType (newNode (CAST,
- newAst_LINK (copyLinkChain (currFunc->type->next)),
- tree->right));
+ newAst_LINK (copyLinkChain (currFunc->type->next)),
+ tree->right),
+ RESULT_CHECK);
}
RRVAL (tree) = 1;
if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
{
- werror (E_VOID_FUNC, currFunc->name);
+ werror (W_VOID_FUNC, currFunc->name);
goto errorTreeReturn;
}
/* the switch value must be an integer */
if (!IS_INTEGRAL (LTYPE (tree)))
{
- werror (E_SWITCH_NON_INTEGER);
+ werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
goto errorTreeReturn;
}
LRVAL (tree) = 1;
/*----------------------------*/
case FOR:
- decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
- decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
- decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
+ decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
+ decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
+ decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
/* if the for loop is reversible then
reverse it otherwise do what we normally
AST_FOR (tree, initExpr),
AST_FOR (tree, condExpr),
AST_FOR (tree, loopExpr),
- tree->left));
+ tree->left), RESULT_CHECK);
}
+ case PARAM:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "node PARAM shouldn't be processed here");
+ /* but in processParams() */
+ return tree;
default:
TTYPE (tree) = TETYPE (tree) = NULL;
return tree;
sizeofOp (sym_link * type)
{
char buff[10];
+ int size;
/* make sure the type is complete and sane */
checkTypeSanity(type, "(sizeof)");
/* get the size and convert it to character */
- sprintf (buff, "%d", getSize (type));
+ SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
+ if (!size && !IS_VOID(type))
+ werror (E_SIZEOF_INCOMPLETE_TYPE);
/* now convert into value */
return constVal (buff);
static int localLbl = 0;
symbol *localLabel;
- sprintf (buffer, "_and_%d", localLbl++);
+ SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
localLabel = newSymbol (buffer, NestLevel);
tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
static int localLbl = 0;
symbol *localLabel;
- sprintf (buffer, "_or_%d", localLbl++);
+ SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
localLabel = newSymbol (buffer, NestLevel);
tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
ast *ex;
/* if the block has nothing */
- if (!body)
+ if (!body && !decl)
return NULL;
ex = newNode (BLOCK, NULL, body);
ex->values.sym = decl;
-
+
ex->right = ex->right;
ex->level++;
ex->lineno = 0;
label = newSymbol (label->name, label->level);
/* change the name before putting it in add _ */
- sprintf (name, "%s", label->name);
+ SNPRINTF(name, sizeof(name), "%s", label->name);
/* put the label in the LabelSymbol table */
/* but first check if a label of the same */
/* then case is out of context */
if (!swStat)
{
- werror (E_CASE_CONTEXT);
+ werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
return NULL;
}
- caseVal = decorateType (resolveSymbols (caseVal));
+ caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
/* if not a constant then error */
if (!IS_LITERAL (caseVal->ftype))
{
- werror (E_CASE_CONSTANT);
+ werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
return NULL;
}
/* if not a integer than error */
if (!IS_INTEGRAL (caseVal->ftype))
{
- werror (E_CASE_NON_INTEGER);
+ werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
return NULL;
}
{
pval->next = caseVal->opval.val;
}
+ else if ((int) floatFromVal (val) == cVal)
+ {
+ werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
+ "case");
+ return NULL;
+ }
else
{
/* we found a value greater than */
}
/* create the case label */
- sprintf (caseLbl, "_case_%d_%d",
+ SNPRINTF(caseLbl, sizeof(caseLbl),
+ "_case_%d_%d",
swStat->values.switchVals.swNum,
(int) floatFromVal (caseVal->opval.val));
/* createDefault - creates the parse tree for the default statement */
/*-----------------------------------------------------------------*/
ast *
-createDefault (ast * swStat, ast * stmnt)
+createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
{
char defLbl[SDCC_NAME_MAX + 1];
/* then case is out of context */
if (!swStat)
{
- werror (E_CASE_CONTEXT);
+ werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
+ return NULL;
+ }
+
+ if (swStat->values.switchVals.swDefault)
+ {
+ werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
+ "default");
return NULL;
}
swStat->values.switchVals.swDefault = 1;
/* create the label */
- sprintf (defLbl, "_default_%d", swStat->values.switchVals.swNum);
+ SNPRINTF (defLbl, sizeof(defLbl),
+ "_default_%d", swStat->values.switchVals.swNum);
return createLabel (newSymbol (defLbl, 0), stmnt);
}
}
/* create the labels */
- sprintf (buffer, "_iffalse_%d", Lblnum);
+ SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
ifFalse = newSymbol (buffer, NestLevel);
/* if no else body then end == false */
if (!elseBody)
ifEnd = ifFalse;
else
{
- sprintf (buffer, "_ifend_%d", Lblnum);
+ SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
ifEnd = newSymbol (buffer, NestLevel);
}
- sprintf (buffer, "_iftrue_%d", Lblnum);
+ SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
ifTrue = newSymbol (buffer, NestLevel);
Lblnum++;
if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
(j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
return tree;
+
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+ return tree;
- return decorateType (newNode (GETHBIT, tree->left->left, NULL));
+ return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
}
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext0;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
}
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext1;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext2;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
return root;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
return root;
}
+/*-----------------------------------------------------------------*/
+/* optimizeSWAP :- optimize for nibble/byte/word swaps */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeSWAP (ast * root)
+{
+ /* will look for trees of the form
+ (?expr << 4) | (?expr >> 4) or
+ (?expr >> 4) | (?expr << 4) will make that
+ 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 (!IS_BITOR (root))
+ return root;
+
+ /* (?expr << 4) | (?expr >> 4) */
+ if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
+ || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
+ {
+
+ if (!SPEC_USIGN (TETYPE (root->left->left)))
+ return root;
+
+ if (!IS_AST_LIT_VALUE (root->left->right) ||
+ !IS_AST_LIT_VALUE (root->right->right))
+ return root;
+
+ /* make sure it is the same expression */
+ if (!isAstEqual (root->left->left,
+ root->right->left))
+ return root;
+
+ if (AST_LIT_VALUE (root->left->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ if (AST_LIT_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ /* make sure the port supports SWAP */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
+ return root;
+
+ /* found it : create the AST */
+ return newNode (SWAP, root->left->left, NULL);
+ }
+
+
+ /* not found return root */
+ return root;
+}
+
/*-----------------------------------------------------------------*/
/* optimizeCompare - otimizes compares for bit variables */
/*-----------------------------------------------------------------*/
break;
}
- return decorateType (optExpr);
+ return decorateType (optExpr, RESULT_CHECK);
}
vleft = (root->left->type == EX_VALUE ?
break;
}
}
- return decorateType (resolveSymbols (optExpr));
+ return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
} /* end-of-if of BITVAR */
noOptimize:
addSymChain (name);
allocVariables (name);
}
- name->lastLine = yylineno;
+ name->lastLine = mylineno;
currFunc = name;
/* set the stack pointer */
name->stack = SPEC_STAK (fetype) = stack;
/* name needs to be mangled */
- sprintf (name->rname, "%s%s", port->fun_prefix, name->name);
+ SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
body = resolveSymbols (body); /* resolve the symbols */
- body = decorateType (body); /* propagateType & do semantic checks */
+ body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
+
ex = newAst_VALUE (symbolVal (name)); /* create name */
ex = newNode (FUNCTION, ex, body);
{
GcurMemmap = statsg;
codeOutFile = statsg->oFile;
- eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
+ eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
staticAutos = NULL;
}
/* dealloc the block variables */
processBlockVars (body, &stack, DEALLOCATE);
+ outputDebugStackSymbols();
/* deallocate paramaters */
deallocParms (FUNC_ARGS(name->type));
applyToSet (operKeyReset, resetParmKey);
if (options.debug)
- cdbStructBlock (1, cdbFile);
+ cdbStructBlock(1);
cleanUpLevel (LabelTab, 0);
cleanUpBlock (StructTab, 1);
}
-#define INDENT(x,f) { int i ; for (i=0;i < x; i++) fprintf(f," "); }
+#define INDENT(x,f) { int i ; fprintf (f, "%d:", 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 */
fprintf(outfile,"ERROR_NODE(%p)\n",tree);
}
-
+
/* print the line */
/* if not block & function */
if (tree->type == EX_OP &&
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 (",
+ fprintf(outfile,"FUNCTION (%s=%p) type (",
tree->left->opval.val->name, tree);
- printTypeChain (tree->ftype,outfile);
+ printTypeChain (tree->left->opval.val->type->next,outfile);
fprintf(outfile,") args (");
do {
if (arg) {
decls->name, decls);
printTypeChain(decls->type,outfile);
fprintf(outfile,")\n");
-
- decls = decls->next;
+
+ decls = decls->next;
}
ast_print(tree->right,outfile,indent+2);
INDENT(indent,outfile);
return;
}
if (tree->opval.op == NULLOP) {
- fprintf(outfile,"\n");
ast_print(tree->left,outfile,indent);
- fprintf(outfile,"\n");
ast_print(tree->right,outfile,indent);
return ;
}
/* just get the type */
if (tree->type == EX_VALUE) {
- if (IS_LITERAL (tree->opval.val->etype)) {
- fprintf(outfile,"CONSTANT (%p) value = %d, 0x%x, %g", tree,
- (int) floatFromVal(tree->opval.val),
- (int) floatFromVal(tree->opval.val),
- floatFromVal(tree->opval.val));
+ 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) {
/* depending on type of operator do */
-
+
switch (tree->opval.op) {
/*------------------------------------------------------------------*/
/*----------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ 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);
+ 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);
+ ast_print(tree->left,outfile,indent+2); /* postdecrement case */
+ ast_print(tree->right,outfile,indent+2); /* predecrement case */
return ;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* bitwise and */
/*----------------------------*/
- case '&':
+ case '&':
if (tree->right) {
fprintf(outfile,"& (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* division */
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);
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* assignment operators */
ast_print(tree->right,outfile,indent+2);
return;
case OR_ASSIGN:
- fprintf(outfile,"ORASS(*=) (%p) type (",tree);
+ 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);
+ 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 LEFT_ASSIGN:
- fprintf(outfile,"LSHFTASS(*=) (%p) type (",tree);
+ fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
fprintf(outfile,")\n");
ast_print(tree->left,outfile,indent+2);
fprintf(outfile,"IF (%p) \n",tree);
ast_print(tree->left,outfile,indent+2);
if (tree->trueLabel) {
- INDENT(indent,outfile);
+ INDENT(indent+2,outfile);
fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
}
if (tree->falseLabel) {
- INDENT(indent,outfile);
+ 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 */
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 ;
}
{
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++;
+
+ errors += astErrors(t->left);
+ errors += astErrors(t->right);
+ }
+
+ return errors;
+}