what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
+#define DEBUG_CF(x) /* puts(x); */
+
#include "common.h"
int currLineno = 0;
/* 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))
{
- //if (func->type==EX_VALUE && func->opval.val->sym->undefined)
- // return 1; /* Already gave them an undefined function error */
werror (E_TOO_MANY_PARMS);
return 1;
}
/* if defined parameters present but no actual parameters */
- if (defParm && !actParm)
+ if (defParm && !*actParm)
{
werror (E_TOO_FEW_PARMS);
return 1;
}
- if (IS_VOID(actParm->ftype)) {
- werror (E_VOID_VALUE_USED);
- return 1;
- }
+ /* if this is a PARAM node then match left & right */
+ if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
+ {
+ (*actParm)->decorated = 1;
+ return (processParms (func, defParm,
+ &(*actParm)->left, parmNumber, FALSE) ||
+ processParms (func, defParm ? defParm->next : NULL,
+ &(*actParm)->right, parmNumber, rightmost));
+ }
+ else if (defParm) /* not vararg */
+ {
+ /* If we have found a value node by following only right-hand links,
+ * then we know that there are no more values after us.
+ *
+ * Therefore, if there are more defined parameters, the caller didn't
+ * supply enough.
+ */
+ if (rightmost && defParm->next)
+ {
+ werror (E_TOO_FEW_PARMS);
+ return 1;
+ }
+ }
+
+ /* decorate parameter */
+ resultType = defParm ? getResultTypeFromType (defParm->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))
{
- 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)->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) {
- werrorfl (filename, 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);
}
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;
werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
}
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;
+ 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);
}
// 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) {
- werrorfl (filename, sym->lineDef,
+ werrorfl (sym->fileDef, sym->lineDef,
W_EXCESS_INITIALIZERS, "scalar",
sym->name);
}
work = initAggregates (sym, sym->ival, NULL);
} else {
if (getNelements(sym->type, sym->ival)>1) {
- werrorfl (filename, sym->lineDef,
+ werrorfl (sym->fileDef, sym->lineDef,
W_EXCESS_INITIALIZERS, "scalar",
sym->name);
}
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))
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);
}
tree->right->right &&
(tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
{
- if (IS_LITERAL (RTYPE (tree->right)) ^
+ if (IS_LITERAL (RTYPE (tree->right)) !=
IS_LITERAL (LTYPE (tree->right)))
{
tree->right->decorated = 0;
tree->left->right &&
(tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
{
- if (IS_LITERAL (RTYPE (tree->left)) ^
+ if (IS_LITERAL (RTYPE (tree->left)) !=
IS_LITERAL (LTYPE (tree->left)))
{
tree->left->decorated = 0;
}
/*-----------------------------------------------------------------*/
-/* 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_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))
+ 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 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;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 */
}
}
#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);
- 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));
+ 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), FALSE);
+ TTYPE (tree) = computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op);
TETYPE (tree) = getSpec (TTYPE (tree));
/* if left is a literal exchange left & right */
ast *litTree = searchLitOp (tree, &parent, "&");
if (litTree)
{
- ast *tTree = litTree->left;
+ DEBUG_CF("&")
+ ast *tTree = litTree->left;
litTree->left = tree->right;
tree->right = tTree;
/* both operands in tTree are literal now */
- decorateType (parent);
+ decorateType (parent, resultType);
}
}
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);
+ return decorateType (wtree, RESULT_CHECK);
}
/* if left is a literal exchange left & right */
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);
+ decorateType (parent, resultType);
}
}
/* fall through */
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);
+ decorateType (parent, resultType);
}
}
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- FALSE));
+ resultType,
+ tree->opval.op));
return tree;
}
LRVAL (tree) = RRVAL (tree) = 1;
+
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- TRUE));
+ resultType,
+ tree->opval.op));
/* if right is a literal and */
/* left is also a division by a literal then */
if (IS_LITERAL (RTYPE (litTree)))
{
/* foo_div */
- litTree->right = newNode ('*', litTree->right, tree->right);
+ 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);
+ decorateType (parent, resultType);
}
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, resultType);
}
}
}
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- TRUE));
+ resultType,
+ tree->opval.op));
return tree;
/*------------------------------------------------------------------*/
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);
+ decorateType (parent, resultType);
}
}
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),
- TRUE));
+ computeType (LTYPE (tree),
+ RTYPE (tree),
+ resultType,
+ tree->opval.op));
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 = valPlus (valFromType (LETYPE (tree)),
valFromType (RETYPE (tree)));
tree->right = tree->left = NULL;
if (litTree->opval.op == '+')
{
/* foo_aa */
+ DEBUG_CF("+ 1 AA")
ast *tTree = litTree->left;
litTree->left = tree->right;
tree->right = tree->left;
{
if (IS_LITERAL (RTYPE (litTree)))
{
+ DEBUG_CF("+ 2 ASR")
/* foo_asr */
ast *tTree = litTree->left;
litTree->left = tree->right;
}
else
{
+ DEBUG_CF("+ 3 ASL")
/* foo_asl */
ast *tTree = litTree->right;
litTree->right = tree->right;
tree->opval.op = '-';
}
}
- decorateType (parent);
+ decorateType (parent, resultType);
}
}
TETYPE (tree) = getSpec (TTYPE (tree) =
LTYPE (tree));
else
- TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- RTYPE (tree),
- FALSE));
+ {
+ 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;
/*------------------------------------------------------------------*/
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),
- FALSE));
+ {
+ 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 (litTree->opval.op == '+')
{
/* foo_sa */
- litTree->right = newNode ('-', litTree->right, tree->right);
- litTree->right->lineno = tree->lineno;
-
- tree->right->opval.val = constVal ("0");
+ 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 */
- litTree->right = newNode ('+', tree->right, litTree->right);
- litTree->right->lineno = tree->lineno;
-
- tree->right->opval.val = constVal ("0");
+ 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);
+ decorateType (litParent, resultType);
}
}
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)))
LRVAL (tree) = RRVAL (tree) = 1;
if (tree->opval.op == LEFT_OP)
{
- /* promote char to int */
TETYPE (tree) = getSpec (TTYPE (tree) =
- computeType (LTYPE (tree),
- LTYPE (tree), /* no, not RTYPE! */
- TRUE));
+ computeType (LTYPE (tree),
+ NULL,
+ resultType,
+ tree->opval.op));
}
else /* RIGHT_OP */
{
/* 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))) {
/*----------------------------*/
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)))
}
}
/* if unsigned value < 0 then always false */
- /* if (unsigned value) > 0 then (unsigned value) */
- if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) &&
+ /* 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 == '<')
}
if (tree->opval.op == '>')
{
- return tree->left;
+ 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 */
/*----------------------------*/
case SIZEOF: /* evaluate wihout code generation */
/* change the type to a integer */
+ {
+ int size = getSize (tree->right->ftype);
+ SNPRINTF(buffer, sizeof(buffer), "%d", size);
+ if (!size && !IS_VOID(tree->right->ftype))
+ werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
+ }
tree->type = EX_VALUE;
- SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
tree->opval.val = constVal (buffer);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
/*----------------------------*/
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), FALSE);
+ TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+ resultType, tree->opval.op);
TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- FALSE));
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
werror (E_CODE_WRITE, "-=");
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- FALSE));
+ RESULT_TYPE_NOPROM,
+ tree->opval.op));
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;
/* 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)))
{
- reverseParms (tree->right);
+ werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+ goto errorTreeReturn;
}
- if (IS_CODEPTR(LTYPE(tree))) {
- TTYPE(tree) = LTYPE(tree)->next->next;
- } else {
- TTYPE(tree) = LTYPE(tree)->next;
+ {
+ 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));
}
- TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
/*------------------------------------------------------------------*/
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;
/*----------------------------*/
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 */
- SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
+ SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
+ if (!size && !IS_VOID(type))
+ werror (E_SIZEOF_INCOMPLETE_TYPE);
/* now convert into value */
return constVal (buff);
return NULL;
}
- caseVal = decorateType (resolveSymbols (caseVal));
+ caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
/* if not a constant then error */
if (!IS_LITERAL (caseVal->ftype))
{
&& !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;
}
ast_print(tree->left,outfile,indent+2);
ast_print(tree->right,outfile,indent+2);
return ;
-
+
/*------------------------------------------------------------------*/
/*----------------------------*/
/* assignment operators */