int noLineno = 0;
int noAlloc = 0;
symbol *currFunc=NULL;
-static ast *createIval (ast *, sym_link *, initList *, ast *);
-static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
+static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
ast *optimizeSWAP (ast *);
-ast *optimizeGetHbit (ast *);
+ast *optimizeGetHbit (ast *, RESULT_TYPE);
+ast *optimizeGetAbit (ast *, RESULT_TYPE);
+ast *optimizeGetByte (ast *, RESULT_TYPE);
+ast *optimizeGetWord (ast *, RESULT_TYPE);
ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
int inInitMode = 0;
dest->lineno = src->lineno;
dest->level = src->level;
dest->funcName = src->funcName;
+ dest->reversed = src->reversed;
if (src->ftype)
dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
}
/* save it */
- addSymChain (sym);
+ addSymChain (&sym);
sym->cdef = 1;
allocVariables (sym);
return sym;
}
/* save it */
- addSymChain (sym);
+ addSymChain (&sym);
sym->cdef = 1;
allocVariables (sym);
return sym;
return;
/* top down if we find a nonParm tree then quit */
- if (ptree->type == EX_OP && ptree->opval.op == PARAM)
+ if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
{
+ /* The various functions expect the parameter tree to be right heavy. */
+ /* Rotate the tree to be left heavy so that after reversal it is */
+ /* right heavy again. */
+ while ((ttree = ptree->right) && ttree->type == EX_OP &&
+ ttree->opval.op == PARAM)
+ {
+ ptree->right = ttree->right;
+ ttree->right = ttree->left;
+ ttree->left = ptree->left;
+ ptree->left = ttree;
+ }
+
+ /* Now reverse */
ttree = ptree->left;
ptree->left = ptree->right;
ptree->right = ttree;
+ ptree->reversed = 1;
reverseParms (ptree->left);
reverseParms (ptree->right);
}
/* if the function is being called via a pointer & */
/* it has not been defined a reentrant then we cannot */
/* have parameters */
- if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+ /* PIC16 port can... */
+ if (!TARGET_IS_PIC16)
{
- werror (W_NONRENT_ARGS);
- fatalError++;
- return 1;
+ if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+ {
+ werror (W_NONRENT_ARGS);
+ fatalError++;
+ return 1;
+ }
}
/* if defined parameters ended but actual parameters */
if (ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
- return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
+ iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+ return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
/* createIvalStruct - generates initial value for structures */
/*-----------------------------------------------------------------*/
static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist)
+createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
{
ast *rast = NULL;
ast *lAst;
break;
sflds->implicit = 1;
lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
- lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
- rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
+ lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+ rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+ iloop, rast, rootValue)),
+ RESULT_TYPE_NONE);
+
}
if (iloop) {
/* createIvalArray - generates code for array initialization */
/*-----------------------------------------------------------------*/
static ast *
-createIvalArray (ast * sym, sym_link * type, initList * ilist)
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
{
ast *rast = NULL;
initList *iloop;
if (IS_CHAR (type->next))
if ((rast = createIvalCharPtr (sym,
type,
- decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+ rootValue)))
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
- /* not the special case */
- if (ilist->type != INIT_DEEP)
- {
- werror (E_INIT_STRUCT, "");
- return NULL;
- }
+ /* not the special case */
+ if (ilist->type != INIT_DEEP)
+ {
+ werror (E_INIT_STRUCT, "");
+ return NULL;
+ }
- iloop = ilist->init.deep;
- lcnt = DCL_ELEM (type);
+ iloop = ilist->init.deep;
+ lcnt = DCL_ELEM (type);
- if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
- {
- ast *aSym;
+ if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+ {
+ ast *aSym;
- aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
-
- rast = newNode(ARRAYINIT, aSym, NULL);
- rast->values.constlist = literalL;
-
- // Make sure size is set to length of initializer list.
- while (iloop)
- {
- size++;
- iloop = iloop->next;
- }
-
- if (lcnt && size > lcnt)
- {
- // Array size was specified, and we have more initializers than needed.
- char *name=sym->opval.val->sym->name;
- int lineno=sym->opval.val->sym->lineDef;
- char *filename=sym->opval.val->sym->fileDef;
-
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
- }
- }
- else
- {
- for (;;)
- {
- ast *aSym;
-
- aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
- aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
- rast = createIval (aSym, type->next, iloop, rast);
- iloop = (iloop ? iloop->next : NULL);
- if (!iloop)
- {
- break;
- }
-
- /* no of elements given and we */
- /* have generated for all of them */
- if (!--lcnt)
- {
- // is this a better way? at least it won't crash
- char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
- int lineno = iloop->lineno;
- char *filename = iloop->filename;
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-
- break;
- }
- }
- }
+ aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
+
+ rast = newNode(ARRAYINIT, aSym, NULL);
+ rast->values.constlist = literalL;
+
+ // Make sure size is set to length of initializer list.
+ while (iloop)
+ {
+ size++;
+ iloop = iloop->next;
+ }
+
+ if (lcnt && size > lcnt)
+ {
+ // Array size was specified, and we have more initializers than needed.
+ char *name=sym->opval.val->sym->name;
+ int lineno=sym->opval.val->sym->lineDef;
+ char *filename=sym->opval.val->sym->fileDef;
+
+ werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ ast *aSym;
+
+ aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
+ aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+ rast = createIval (aSym, type->next, iloop, rast, rootValue);
+ iloop = (iloop ? iloop->next : NULL);
+ if (!iloop)
+ {
+ break;
+ }
+
+ /* no of elements given and we */
+ /* have generated for all of them */
+ if (!--lcnt)
+ {
+ // is this a better way? at least it won't crash
+ char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+ int lineno = iloop->lineno;
+ char *filename = iloop->filename;
+ werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+
+ break;
+ }
+ }
+ }
- /* if we have not been given a size */
- if (!DCL_ELEM (type))
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
{
- /* but this still updates the typedef instead of the instance ! see bug 770487 */
+ /* check, if it's a flexible array */
+ if (IS_STRUCT (AST_VALUE (rootValue)->type))
+ AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
+ else
DCL_ELEM (type) = size;
}
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/* createIvalCharPtr - generates initial values for char pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
+createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
{
ast *rast = NULL;
+ unsigned size = 0;
/* if this is a pointer & right is a literal array then */
/* just assignment will do */
/* 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)
+
+ size = getSize (iexpr->ftype);
+ if (symsize && size>symsize)
{
if (size>(symsize+1))
- werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
- "string", sym->opval.val->sym->name);
+ {
+ char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+ werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+ "string", name);
+ }
size = symsize;
}
// now WE don't need iexpr's symbol anymore
freeStringSymbol(AST_SYMBOL(iexpr));
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
+ {
+ /* check, if it's a flexible array */
+ if (IS_STRUCT (AST_VALUE (rootVal)->type))
+ AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+ else
+ DCL_ELEM (type) = size;
+ }
+
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
return NULL;
/* createIvalPtr - generates initial value for pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalPtr (ast * sym, sym_link * type, initList * ilist)
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
{
ast *rast;
ast *iexpr;
if (ilist->type == INIT_DEEP)
ilist = ilist->init.deep;
- iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
+ iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
/* if character pointer */
if (IS_CHAR (type->next))
- if ((rast = createIvalCharPtr (sym, type, iexpr)))
+ if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
return rast;
return newNode ('=', sym, iexpr);
/* createIval - generates code for initial value */
/*-----------------------------------------------------------------*/
static ast *
-createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
{
ast *rast = NULL;
/* if structure then */
if (IS_STRUCT (type))
- rast = createIvalStruct (sym, type, ilist);
+ rast = createIvalStruct (sym, type, ilist, rootValue);
else
/* if this is a pointer */
if (IS_PTR (type))
- rast = createIvalPtr (sym, type, ilist);
+ rast = createIvalPtr (sym, type, ilist, rootValue);
else
/* if this is an array */
if (IS_ARRAY (type))
- rast = createIvalArray (sym, type, ilist);
+ rast = createIvalArray (sym, type, ilist, rootValue);
else
/* if type is SPECIFIER */
if (IS_SPEC (type))
rast = createIvalType (sym, type, ilist);
if (wid)
- return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
+ return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
else
- return decorateType (resolveSymbols (rast), RESULT_CHECK);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
/* initAggregates - initialises aggregate variables with initv */
/*-----------------------------------------------------------------*/
ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
- return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
+ ast *newAst = newAst_VALUE (symbolVal (sym));
+ return createIval (newAst, sym->type, ival, wid, newAst);
}
/*-----------------------------------------------------------------*/
if (sym->ival)
resolveIvalSym (sym->ival, sym->type);
+#if 1
+ /* if we are PIC16 port,
+ * and this is a static,
+ * and have initial value,
+ * and not S_CODE, don't emit in gs segment,
+ * but allow glue.c:pic16emitRegularMap to put symbol
+ * in idata section */
+ if(TARGET_IS_PIC16 &&
+ IS_STATIC (sym->etype) && sym->ival
+ && SPEC_SCLS(sym->etype) != S_CODE) {
+ SPEC_SCLS (sym->etype) = S_DATA;
+ continue;
+ }
+#endif
+
/* if this is a static variable & has an */
/* initial value the code needs to be lifted */
/* here to the main portion since they can be */
if (noAlloc == 0)
{
/* allocate it */
- addSymChain (sym);
+ addSymChain (&sym);
allocVariables (sym);
}
sym->ival = NULL;
return TRUE;
}
- cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
switch (cexpr->type)
{
value *
constExprValue (ast * cexpr, int check)
{
- cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+ cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
/* if this is not a constant then */
if (!IS_LITERAL (cexpr->ftype))
}
}
+ else
+ return FALSE;
/* check loop expression is of the form <sym>++ */
if (!IS_AST_OP (loopExpr))
case '%':
case LEFT_OP:
case RIGHT_OP:
+ case GETABIT:
+ case GETBYTE:
+ case GETWORD:
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
rloop))));
rloop->lineno=init->lineno;
- return decorateType (rloop, RESULT_CHECK);
+ return decorateType (rloop, RESULT_TYPE_NONE);
}
/* searchLitOp - search tree (*ops only) for an ast with literal */
/*-----------------------------------------------------------------*/
static ast *
-searchLitOp (ast *tree, ast **parent, const char *ops)
+searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
{
ast *ret;
/* addCast - adds casts to a type specified by RESULT_TYPE */
/*-----------------------------------------------------------------*/
static ast *
-addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
{
sym_link *newLink;
bool upCasted = FALSE;
switch (resultType)
{
case RESULT_TYPE_NONE:
- /* char: promote to int */
- if (!upcast ||
+ /* if thing smaller than int must be promoted to int */
+ if (!promote ||
getSize (tree->etype) >= INTSIZE)
+ /* promotion not necessary or already an int */
+ return tree;
+ /* char and bits: promote to int */
+ newLink = newIntLink();
+ upCasted = TRUE;
+ break;
+ case RESULT_TYPE_BIT:
+ if (!promote ||
+ /* already an int */
+ bitsForType (tree->etype) >= 16 ||
+ /* bit to bit operation: don't promote, the code generators
+ hopefully know everything about promotion rules */
+ bitsForType (tree->etype) == 1)
return tree;
newLink = newIntLink();
upCasted = TRUE;
break;
case RESULT_TYPE_CHAR:
if (IS_CHAR (tree->etype) ||
- IS_FLOAT(tree->etype))
+ IS_FLOAT(tree->etype) ||
+ IS_FIXED(tree->etype))
return tree;
newLink = newCharLink();
break;
}
#endif
/* char: promote to int */
- if (!upcast ||
+ if (!promote ||
getSize (tree->etype) >= INTSIZE)
return tree;
newLink = newIntLink();
upCasted = TRUE;
break;
case RESULT_TYPE_OTHER:
- if (!upcast)
+ if (!promote)
return tree;
/* return type is long, float: promote char to int */
if (getSize (tree->etype) >= INTSIZE)
{
switch (tree->opval.op)
{
+ case AND_OP:
+ case OR_OP:
+ return resultType;
case '=':
case '?':
case ':':
/* see if this is a GETHBIT operation if yes
then return that */
{
- ast *otree = optimizeGetHbit (tree);
+ ast *otree = optimizeGetHbit (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETABIT operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetAbit (tree, resultType);
if (otree != tree)
- return decorateType (otree, RESULT_CHECK);
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETBYTE operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetByte (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETWORD operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetWord (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
}
/* if left is a literal exchange left & right */
/* bitwise or */
/*----------------------------*/
case '|':
- /* if the rewrite succeeds then don't go any furthur */
+ /* if the rewrite succeeds then don't go any further */
{
ast *wtree = optimizeRRCRLC (tree);
if (wtree != tree)
- return decorateType (wtree, RESULT_CHECK);
+ return decorateType (wtree, RESULT_TYPE_NONE);
wtree = optimizeSWAP (tree);
if (wtree != tree)
- return decorateType (wtree, RESULT_CHECK);
+ return decorateType (wtree, RESULT_TYPE_NONE);
}
/* if left is a literal exchange left & right */
else
{
/* litTree->left is literal: no gcse possible.
- We can't call decorateType(parent, RESULT_CHECK), because
+ We can't call decorateType(parent, RESULT_TYPE_NONE), because
this would cause an infinit loop. */
parent->decorated = 1;
decorateType (litTree, resultType);
TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
return addCast (tree, resultType, TRUE);
}
- tree->left = addCast (tree->left, resultType, TRUE);
+
+ if (resultType == RESULT_TYPE_BIT &&
+ IS_UNSIGNED (tree->left->etype) &&
+ getSize (tree->left->etype) < INTSIZE)
+ {
+ /* promotion rules are responsible for this strange result:
+ bit -> int -> ~int -> bit
+ uchar -> int -> ~int -> bit
+ */
+ werror(W_COMPLEMENT);
+
+ /* optimize bit-result, even if we optimize a buggy source */
+ tree->type = EX_VALUE;
+ tree->opval.val = constVal ("1");
+ }
+ else
+ tree->left = addCast (tree->left, resultType, TRUE);
LRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
return tree;
return tree;
}
LRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
return tree;
/*------------------------------------------------------------------*/
return tree;
case GETHBIT:
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ case GETABIT:
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+ return tree;
+
+ case GETBYTE:
+ TTYPE (tree) = TETYPE (tree) = newCharLink();
+ return tree;
+
+ case GETWORD:
+ TTYPE (tree) = TETYPE (tree) = newIntLink();
return tree;
case LEFT_OP:
return tree;
}
+ /* see if this is a GETBYTE operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetByte (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
+ /* see if this is a GETWORD operation if yes
+ then return that */
+ {
+ ast *otree = optimizeGetWord (tree, resultType);
+
+ if (otree != tree)
+ return decorateType (otree, RESULT_TYPE_NONE);
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
if (tree->opval.op == LEFT_OP)
{
if (IS_ADDRESS_OF_OP(tree->right)
&& IS_AST_SYM_VALUE (tree->right->left)
&& SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
+
+ symbol * sym = AST_SYMBOL (tree->right->left);
+ unsigned int gptype = 0;
+ unsigned int addr = SPEC_ADDR (sym->etype);
+ if (IS_GENPTR (LTYPE (tree)) && GPTRSIZE > FPTRSIZE)
+ {
+ switch (SPEC_SCLS (sym->etype))
+ {
+ case S_CODE:
+ gptype = GPTYPE_CODE;
+ break;
+ case S_XDATA:
+ gptype = GPTYPE_FAR;
+ break;
+ case S_DATA:
+ case S_IDATA:
+ gptype = GPTYPE_NEAR;
+ break;
+ case S_PDATA:
+ gptype = GPTYPE_XSTACK;
+ break;
+ default:
+ gptype = 0;
+ }
+ addr |= gptype << (8*(GPTRSIZE - 1));
+ }
+
tree->type = EX_VALUE;
tree->opval.val =
- valCastLiteral (LTYPE (tree),
- SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
+ valCastLiteral (LTYPE (tree), addr);
TTYPE (tree) = tree->opval.val->type;
TETYPE (tree) = getSpec (TTYPE (tree));
tree->left = NULL;
return tree;
}
LRVAL (tree) = RRVAL (tree) = 1;
- TTYPE (tree) = TETYPE (tree) = newCharLink ();
+ TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
return tree;
/*------------------------------------------------------------------*/
tree->right); /* val 0 */
tree->right->lineno = tree->lineno;
tree->right->left->lineno = tree->lineno;
- decorateType (tree->right, RESULT_CHECK);
+ decorateType (tree->right, RESULT_TYPE_NONE);
}
}
/* if they are both literal then */
tree->opval.val->type);
return tree;
}
+ /* if one is 'signed char ' and the other one is 'unsigned char' */
+ /* it's necessary to promote to int */
+ if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
+ (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
+ {
+ /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
+ if it's possible to use a 'signed char' */
+
+ /* is left a 'unsigned char'? */
+ if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
+ /* the value range of a 'unsigned char' is 0...255;
+ if the actual value is < 128 it can be changed to signed */
+ (int) floatFromVal (valFromType (RETYPE (tree))) < 128)
+ {
+ /* now we've got 2 'signed char'! */
+ SPEC_USIGN (RETYPE (tree)) = 0;
+ }
+ /* same test for the left operand: */
+ else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
+ (int) floatFromVal (valFromType (LETYPE (tree))) < 128)
+ {
+ SPEC_USIGN (LETYPE (tree)) = 0;
+ }
+ else
+ {
+ werror (W_CMP_SU_CHAR);
+ tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
+ tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
+ }
+ }
+
LRVAL (tree) = RRVAL (tree) = 1;
TTYPE (tree) = TETYPE (tree) = newCharLink ();
return tree;
case V_FLOAT:
typeofv = TYPEOF_FLOAT;
break;
+ case V_FIXED16X16:
+ typeofv = TYPEOF_FIXED16X16;
+ break;
case V_CHAR:
typeofv = TYPEOF_CHAR;
break;
case ':':
/* if they don't match we have a problem */
- if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+ if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
+ (compareType (RTYPE (tree), LTYPE (tree)) == 0))
{
werror (E_TYPE_MISMATCH, "conditional operator", " ");
goto errorTreeReturn;
goto errorTreeReturn;
}
- tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
+ tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
tree->opval.op = '=';
return tree;
}
/* require a function or pointer to function */
- if (!IS_FUNC (LTYPE (tree))
- && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
+ if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
{
werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
goto errorTreeReturn;
sym_link *functype;
parmNumber = 1;
- if (IS_CODEPTR(LTYPE(tree)))
+ if (IS_FUNCPTR (LTYPE (tree)))
functype = LTYPE (tree)->next;
else
functype = LTYPE (tree);
decorateType (newNode (CAST,
newAst_LINK (copyLinkChain (currFunc->type->next)),
tree->right),
- RESULT_CHECK);
+ RESULT_TYPE_NONE);
}
RRVAL (tree) = 1;
/*----------------------------*/
case FOR:
- decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
- decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
- decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
+ decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
+ decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
+ decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
/* 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), RESULT_CHECK);
+ tree->left), RESULT_TYPE_NONE);
}
case PARAM:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
ex = newNode (BLOCK, NULL, body);
ex->values.sym = decl;
- ex->right = ex->right;
ex->level++;
ex->lineno = 0;
return ex;
return NULL;
}
- caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
+ caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
/* if not a constant then error */
if (!IS_LITERAL (caseVal->ftype))
{
}
/*-----------------------------------------------------------------*/
-/* optimizeGetHbit - get highest order bit of the expression */
+/* isShiftRightLitVal _BitAndLitVal - helper function */
/*-----------------------------------------------------------------*/
-ast *
-optimizeGetHbit (ast * tree)
+static ast *
+isShiftRightLitVal_BitAndLitVal (ast * tree)
{
- int i, j;
/* if this is not a bit and */
if (!IS_BITAND (tree))
- return tree;
+ return NULL;
/* will look for tree of the form
- ( expr >> ((sizeof expr) -1) ) & 1 */
+ ( expr >> litval2) & litval1 */
if (!IS_AST_LIT_VALUE (tree->right))
+ return NULL;
+
+ if (!IS_RIGHT_OP (tree->left))
+ return NULL;
+
+ if (!IS_AST_LIT_VALUE (tree->left->right))
+ return NULL;
+
+ return tree->left->left;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitAndPowOf2 - helper function */
+/*-----------------------------------------------------------------*/
+static int
+isBitAndPow2 (ast * tree)
+{
+ /* if this is not a bit and */
+ if (!IS_BITAND (tree))
+ return -1;
+
+ /* will look for tree of the form
+ ( expr & (1 << litval) */
+ if (!IS_AST_LIT_VALUE (tree->right))
+ return -1;
+
+ return powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetHbit - get highest order bit of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
+{
+ int i, j;
+ ast * expr;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ if ((AST_LIT_VALUE (tree->right) != 1) ||
+ ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
+ (j = (getSize (TTYPE (expr)) * 8 - 1))))
+ expr = NULL;
+ }
+ if (!expr && (resultType == RESULT_TYPE_BIT))
+ {
+ expr = tree->left;
+ if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1)
+ expr = NULL;
+ }
+ if (!expr)
return tree;
- if (AST_LIT_VALUE (tree->right) != 1)
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
return tree;
- if (!IS_RIGHT_OP (tree->left))
+ return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetAbit - get a single bit of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
+{
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ if (AST_LIT_VALUE (tree->right) != 1)
+ expr = NULL;
+ count = tree->left->right;
+ }
+ if (!expr && (resultType == RESULT_TYPE_BIT))
+ {
+ int p2 = isBitAndPow2 (tree);
+ if (p2 >= 0)
+ {
+ expr = tree->left;
+ count = newAst_VALUE (valueFromLit (p2));
+ }
+ }
+ if (!expr)
return tree;
- if (!IS_AST_LIT_VALUE (tree->left->right))
+ /* make sure the port supports GETABIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
return tree;
- if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
- (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
+ return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetByte - get a byte of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetByte (ast * tree, RESULT_TYPE resultType)
+{
+ unsigned int i = 0;
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+ count = tree->left->right;
+ if (AST_LIT_VALUE (tree->right) != 0xFF)
+ expr = NULL;
+ }
+ if (!expr && resultType == RESULT_TYPE_CHAR)
+ {
+ /* if this is a right shift over a multiple of 8 */
+ if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+ {
+ i = (unsigned int) AST_LIT_VALUE (tree->right);
+ count = tree->right;
+ expr = tree->left;
+ }
+ }
+ if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
return tree;
- /* make sure the port supports GETHBIT */
+ /* make sure the port supports GETBYTE */
if (port->hasExtBitOp
- && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+ && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
return tree;
- return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
+ return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
+}
+/*-----------------------------------------------------------------*/
+/* optimizeGetWord - get two bytes of the expression */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetWord (ast * tree, RESULT_TYPE resultType)
+{
+ unsigned int i = 0;
+ ast * expr;
+ ast * count = NULL;
+
+ expr = isShiftRightLitVal_BitAndLitVal(tree);
+ if (expr)
+ {
+ i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+ count = tree->left->right;
+ if (AST_LIT_VALUE (tree->right) != 0xFFFF)
+ expr = NULL;
+ }
+ if (!expr && resultType == RESULT_TYPE_INT)
+ {
+ /* if this is a right shift over a multiple of 8 */
+ if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+ {
+ i = (unsigned int) AST_LIT_VALUE (tree->right);
+ count = tree->right;
+ expr = tree->left;
+ }
+ }
+ if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
+ return tree;
+
+ /* make sure the port supports GETWORD */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
+ return tree;
+
+ return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
}
/*-----------------------------------------------------------------*/
}
/*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables */
+/* optimizeCompare - optimizes compares for bit variables */
/*-----------------------------------------------------------------*/
static ast *
optimizeCompare (ast * root)
break;
}
- return decorateType (optExpr, RESULT_CHECK);
+ return decorateType (optExpr, RESULT_TYPE_NONE);
}
vleft = (root->left->type == EX_VALUE ?
break;
}
}
- return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
+ return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
} /* end-of-if of BITVAR */
noOptimize:
}
else
{
- addSymChain (name);
+ addSymChain (&name);
allocVariables (name);
}
name->lastLine = mylineno;
currFunc = name;
/* set the stack pointer */
- /* PENDING: check this for the mcs51 */
- stackPtr = -port->stack.direction * port->stack.call_overhead;
+ stackPtr = -port->stack.direction * port->stack.call_overhead;
+ xstackPtr = 0;
+
if (IFFUNC_ISISR (name->type))
stackPtr -= port->stack.direction * port->stack.isr_overhead;
- if (IFFUNC_ISREENT (name->type) || options.stackAuto)
- stackPtr -= port->stack.direction * port->stack.reent_overhead;
- xstackPtr = -port->stack.direction * port->stack.call_overhead;
+ if (IFFUNC_ISREENT (name->type) || options.stackAuto)
+ {
+ if (options.useXstack)
+ xstackPtr -= port->stack.direction * port->stack.reent_overhead;
+ else
+ stackPtr -= port->stack.direction * port->stack.reent_overhead;
+ }
fetype = getSpec (name->type); /* get the specifier for the function */
/* if this is a reentrant function then */
{
GcurMemmap = statsg;
codeOutFile = statsg->oFile;
- eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
+ eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
staticAutos = NULL;
}
return;
/*------------------------------------------------------------------*/
/*----------------------------*/
- /* compliment */
+ /* complement */
/*----------------------------*/
case '~':
fprintf(outfile,"COMPL (%p) type (",tree);
fprintf(outfile,")\n");
ast_print(tree->left,outfile,indent+2);
return ;
+ case GETABIT:
+ fprintf(outfile,"GETABIT (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case GETBYTE:
+ fprintf(outfile,"GETBYTE (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
+ case GETWORD:
+ fprintf(outfile,"GETWORD (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->right,outfile,indent+2);
+ return ;
case LEFT_OP:
fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
printTypeChain(tree->ftype,outfile);