ex->level = NestLevel;
ex->block = currBlockno;
ex->initMode = inInitMode;
+ ex->seqPoint = seqPointNo;
return ex;
}
/*-----------------------------------------------------------------*/
/* isAstEqual - compares two asts & returns 1 if they are equal */
/*-----------------------------------------------------------------*/
-int
+static int
isAstEqual (ast * t1, ast * t2)
{
if (!t1 && !t2)
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;
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
/* 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;
+
/* if none of them exist */
if (!defParm && !actParm)
return 0;
- if (defParm) {
- if (getenv("DEBUG_SANITY")) {
- fprintf (stderr, "processParms: %s ", defParm->name);
+ if (defParm)
+ {
+ if (getenv("DEBUG_SANITY"))
+ {
+ fprintf (stderr, "processParms: %s ", defParm->name);
+ }
+ /* make sure the type is complete and sane */
+ checkTypeSanity(defParm->etype, defParm->name);
}
- /* make sure the type is complete and sane */
- checkTypeSanity(defParm->etype, defParm->name);
- }
/* if the function is being called via a pointer & */
/* it has not been defined a reentrant then we cannot */
/* exist and this is not defined as a variable arg */
if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
{
+ /* if (func->type==EX_VALUE && func->opval.val->sym->undefined) */
+ /* return 1; *//* Already gave them an undefined function error */
werror (E_TOO_MANY_PARMS);
return 1;
}
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))
}
ftype = actParm->ftype;
-
- /* If it's a small integer, upcast to int. */
+
+ /* If it's a char, upcast to int. */
if (IS_INTEGRAL (ftype)
&& (getSize (ftype) < (unsigned) INTSIZE))
{
- if (IS_AST_OP(actParm) &&
- (actParm->opval.op == LEFT_OP ||
- actParm->opval.op == '*' ||
- actParm->opval.op == '+' ||
- actParm->opval.op == '-') &&
- actParm->right) {
- // we should cast an operand instead of the result
- actParm->decorated = 0;
- actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
- actParm->left);
- actParm = decorateType(actParm);
- } else {
- 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->decorated = 0; /* force typechecking */
+ decorateType (actParm, RESULT_TYPE_NONE);
}
return 0;
- }
+ } /* vararg */
/* if defined parameters ended but actual has not & */
/* reentrant */
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
+
+ /* 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)
{
- 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->decorated = 0; /* force typechecking */
+ decorateType (actParm, resultType);
}
/* make a copy and change the regparm type to the defined parm */
(*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 (filename, 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;
char *name=sym->opval.val->sym->name;
int lineno=sym->opval.val->sym->lineDef;
- 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);
+ werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
break;
}
DCL_ELEM (type) = size;
}
- return decorateType (resolveSymbols (rast));
+ return decorateType (resolveSymbols (rast), RESULT_CHECK);
}
char *s = SPEC_CVAL (iexpr->etype).v_char;
int i = 0;
int size = getSize (iexpr->ftype);
+ int symsize = getSize (type);
+
+ if (size>symsize)
+ {
+ if (size>(symsize+1))
+ werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+ "string", sym->opval.val->sym->name);
+ size = symsize;
+ }
for (i=0;i<size;i++)
{
// now WE don't need iexpr's symbol anymore
freeStringSymbol(AST_SYMBOL(iexpr));
- return decorateType (resolveSymbols (rast));
+ 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))
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 (filename, sym->lineDef,
+ W_EXCESS_INITIALIZERS, "scalar",
+ sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
list2expr (sym->ival));
work = initAggregates (sym, sym->ival, NULL);
} else {
if (getNelements(sym->type, sym->ival)>1) {
- werror (W_EXCESS_INITIALIZERS, "scalar",
- sym->name, sym->lineDef);
+ werrorfl (filename, sym->lineDef,
+ W_EXCESS_INITIALIZERS, "scalar",
+ sym->name);
}
work = newNode ('=', newAst_VALUE (symbolVal (sym)),
list2expr (sym->ival));
return TRUE;
}
- cexpr = decorateType (resolveSymbols (cexpr));
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
switch (cexpr->type)
{
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))
else
return FALSE;
}
-
+
return astHasSymbol (tree->left, sym) ||
astHasSymbol (tree->right, sym);
}
case '?':
case ':':
case SIZEOF: /* evaluate wihout code generation */
-
+
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
return FALSE;
if (astHasVolatile (pbody->left))
return FALSE;
-
+
if (astHasDeref(pbody->right)) return FALSE;
return isConformingBody (pbody->left, sym, body) &&
rloop))));
rloop->lineno=init->lineno;
- return decorateType (rloop);
+ return decorateType (rloop, RESULT_CHECK);
}
}
/*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type checking */
-/* this is done bottom up, since type have to flow upwards */
-/* it also does constant folding, and paramater checking */
+/* getResultFromType */
+/*-----------------------------------------------------------------*/
+RESULT_TYPE
+getResultTypeFromType (sym_link *type)
+{
+ /* type = getSpec (type); */
+ if (IS_BITVAR (type))
+ return RESULT_TYPE_BIT;
+ if (IS_BITFIELD (type))
+ return RESULT_TYPE_CHAR;
+ 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 (getSize (tree->etype) <= 1)
+ 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);
+ /* 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 '^':
+ return resultType;
+ case '&':
+ if (!tree->right)
+ /* can be unary */
+ return RESULT_TYPE_NONE;
+ else
+ return resultType;
+ default:
+ return RESULT_TYPE_NONE;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
/*------------------------------------------------------------------*/
/*----------------------------*/
- /* leaf has been reached */
+/* leaf has been reached */
/*----------------------------*/
lineno=tree->lineno;
/* if this is of type 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);
+
+ 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->right = dtr;
if ((dtl && dtl->isError) || (dtr && dtr->isError))
return tree;
-
- if (IS_AST_OP(tree) &&
- (tree->opval.op == CAST || tree->opval.op == '=') &&
- (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
- (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) {
- // this is a cast/assign to a bigger type
- if (IS_AST_OP(tree->right) &&
- IS_INTEGRAL(tree->right->ftype) &&
- (tree->right->opval.op == LEFT_OP ||
- tree->right->opval.op == '*' ||
- tree->right->opval.op == '+' ||
- tree->right->opval.op == '-') &&
- tree->right->right) {
- // we should cast an operand instead of the result
- tree->right->decorated = 0;
- tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
- tree->right->left);
- tree->right = decorateType(tree->right);
- }
- }
}
/* 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);
return tree;
ast *otree = optimizeGetHbit (tree);
if (otree != tree)
- return decorateType (otree);
+ return decorateType (otree, RESULT_CHECK);
}
- TTYPE (tree) =
- computeType (LTYPE (tree), RTYPE (tree));
+ tree->left = addCast (tree->left, resultType, FALSE);
+ tree->right = addCast (tree->right, resultType, FALSE);
+ TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
TETYPE (tree) = getSpec (TTYPE (tree));
/* if left is a literal exchange left & right */
litTree->left = tree->right;
tree->right = tTree;
/* both operands in tTree are literal now */
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
}
LRVAL (tree) = RRVAL (tree) = 1;
+
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);
-
- // fall through
+ return decorateType (wtree, RESULT_CHECK);
}
/* if left is a literal exchange left & right */
litTree->left = tree->right;
tree->right = tTree;
/* both operands in tTree are literal now */
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
}
+ /* fall through */
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* bitwise xor */
/* 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)))
+ if (IS_LITERAL (RTYPE (tree)) &&
+ tree->opval.op == '^') /* the same source is used by 'bitwise or' */
{
ast *parent;
ast *litTree = searchLitOp (tree, &parent, "^");
litTree->left = tree->right;
tree->right = tTree;
/* both operands in litTree are literal now */
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
}
LRVAL (tree) = RRVAL (tree) = 1;
+ tree->left = addCast (tree->left, resultType, FALSE);
+ tree->right = addCast (tree->right, resultType, FALSE);
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
+
+ return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
/* if right is a literal and */
/* left is also a division by a literal then */
litTree->right->lineno = tree->lineno;
tree->right->opval.val = constVal ("1");
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
else
{
/* litTree->left is literal: no gcse possible.
- We can't call decorateType(parent), because
+ We can't call decorateType(parent, RESULT_CHECK), because
this would cause an infinit loop. */
parent->decorated = 1;
- decorateType (litTree);
+ decorateType (litTree, RESULT_CHECK);
}
}
}
LRVAL (tree) = RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
return tree;
/*------------------------------------------------------------------*/
litTree->left = tree->right;
tree->right = tTree;
/* both operands in litTree are literal now */
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
}
LRVAL (tree) = RRVAL (tree) = 1;
+ tree->left = addCast (tree->left, resultType, FALSE);
+ tree->right = addCast (tree->right, resultType, FALSE);
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree)));
-
- /* 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))) {
- SPEC_NOUN(TETYPE(tree)) = V_INT;
- }
-
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+
return tree;
/*------------------------------------------------------------------*/
tree->opval.op = '-';
}
}
- decorateType (parent);
+ decorateType (parent, RESULT_CHECK);
}
}
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 == RESULT_TYPE_CHAR ? FALSE : TRUE));
+ }
+
return 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 == RESULT_TYPE_CHAR ? FALSE : TRUE));
+ }
LRVAL (tree) = RRVAL (tree) = 1;
tree->right = tTree;
}
}
- decorateType (litParent);
+ decorateType (litParent, RESULT_CHECK);
}
}
return tree;
return tree;
}
+ LRVAL (tree) = RRVAL (tree) = 1;
+ if (tree->opval.op == LEFT_OP)
+ {
+ tree->left = addCast (tree->left, resultType, TRUE);
+ TETYPE (tree) = getSpec (TTYPE (tree) =
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+ }
+ else /* RIGHT_OP */
+ {
+ /* no promotion necessary */
+ TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+ if (IS_LITERAL (TTYPE (tree)))
+ SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+ }
+
/* if only the right side is a literal & we are
shifting more than size of the left operand then zero */
if (IS_LITERAL (RTYPE (tree)) &&
- ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
- (getSize (LTYPE (tree)) * 8))
+ ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
+ (getSize (TETYPE (tree)) * 8))
{
if (tree->opval.op==LEFT_OP ||
- (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
- lineno=tree->lineno;
- werror (W_SHIFT_CHANGED,
- (tree->opval.op == LEFT_OP ? "left" : "right"));
- tree->type = EX_VALUE;
- tree->left = tree->right = NULL;
- tree->opval.val = constVal ("0");
- TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
- return tree;
- }
+ (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;
+ }
}
- LRVAL (tree) = RRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
- if (IS_LITERAL (TTYPE (tree)))
- SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+
return tree;
/*------------------------------------------------------------------*/
/* 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))) {
/* if the right is a literal replace the tree */
if (IS_LITERAL (RETYPE (tree))) {
- if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
+ #if 0
+ if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
/* rewrite (type *)litaddr
as &temp
and define type at litaddr temp
TLVAL (newTree) = 1;
return newTree;
}
+ #endif
if (!IS_PTR (LTYPE (tree))) {
tree->type = EX_VALUE;
tree->opval.val =
}
}
/* 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 the parent is an ifx, then we could do */
+ /* return tree->left; */
+ tree->opval.op = '?';
+ tree->right = newNode (':',
+ newAst_VALUE (constVal ("1")),
+ tree->right); /* val 0 */
+ tree->right->lineno = tree->lineno;
+ tree->right->left->lineno = tree->lineno;
+ decorateType (tree->right, RESULT_CHECK);
+ }
+ }
/* if they are both literal then */
/* rewrite the tree */
if (IS_LITERAL (RTYPE (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), FALSE);
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
werror (E_CODE_WRITE, "-=");
RRVAL (tree) = 1;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
- RTYPE (tree)));
+ RTYPE (tree),
+ FALSE));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
werror (E_CODE_WRITE, "+=");
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;
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;
/* 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;
/* 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 */
/* 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;
}
&& !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);
}
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:
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;
}
fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
else
fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
- fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) 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 */
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* assignment operators */