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 *);
/* createIvalStruct - generates initial value for structures */
/*-----------------------------------------------------------------*/
static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist)
+createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
{
ast *rast = NULL;
ast *lAst;
sflds->implicit = 1;
lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
- rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_TYPE_NONE);
+ rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+ iloop, rast, rootValue)),
+ RESULT_TYPE_NONE);
+
}
if (iloop) {
/* createIvalArray - generates code for array initialization */
/*-----------------------------------------------------------------*/
static ast *
-createIvalArray (ast * sym, sym_link * type, initList * ilist)
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
{
ast *rast = NULL;
initList *iloop;
if (IS_CHAR (type->next))
if ((rast = createIvalCharPtr (sym,
type,
- decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE))))
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+ rootValue)))
return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
- /* not the special case */
- if (ilist->type != INIT_DEEP)
- {
- werror (E_INIT_STRUCT, "");
- return NULL;
- }
+ /* not the special case */
+ if (ilist->type != INIT_DEEP)
+ {
+ werror (E_INIT_STRUCT, "");
+ return NULL;
+ }
- iloop = ilist->init.deep;
- lcnt = DCL_ELEM (type);
+ iloop = ilist->init.deep;
+ lcnt = DCL_ELEM (type);
- if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
- {
- ast *aSym;
+ if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+ {
+ ast *aSym;
- aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
-
- rast = newNode(ARRAYINIT, aSym, NULL);
- rast->values.constlist = literalL;
-
- // Make sure size is set to length of initializer list.
- while (iloop)
- {
- size++;
- iloop = iloop->next;
- }
-
- if (lcnt && size > lcnt)
- {
- // Array size was specified, and we have more initializers than needed.
- char *name=sym->opval.val->sym->name;
- int lineno=sym->opval.val->sym->lineDef;
- char *filename=sym->opval.val->sym->fileDef;
-
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
- }
- }
- else
- {
- for (;;)
- {
- ast *aSym;
-
- aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
- aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
- rast = createIval (aSym, type->next, iloop, rast);
- iloop = (iloop ? iloop->next : NULL);
- if (!iloop)
- {
- break;
- }
-
- /* no of elements given and we */
- /* have generated for all of them */
- if (!--lcnt)
- {
- // is this a better way? at least it won't crash
- char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
- int lineno = iloop->lineno;
- char *filename = iloop->filename;
- werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-
- break;
- }
- }
- }
+ aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
+
+ rast = newNode(ARRAYINIT, aSym, NULL);
+ rast->values.constlist = literalL;
+
+ // Make sure size is set to length of initializer list.
+ while (iloop)
+ {
+ size++;
+ iloop = iloop->next;
+ }
+
+ if (lcnt && size > lcnt)
+ {
+ // Array size was specified, and we have more initializers than needed.
+ 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_TYPE_NONE);
+ return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/* createIvalCharPtr - generates initial values for char pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
+createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
{
ast *rast = NULL;
+ unsigned size = 0;
/* if this is a pointer & right is a literal array then */
/* just assignment will do */
/* 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));
+ /* if we have not been given a size */
+ if (!DCL_ELEM (type))
+ {
+ /* check, if it's a flexible array */
+ if (IS_STRUCT (AST_VALUE (rootVal)->type))
+ AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+ else
+ DCL_ELEM (type) = size;
+ }
+
return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
}
/* createIvalPtr - generates initial value for pointers */
/*-----------------------------------------------------------------*/
static ast *
-createIvalPtr (ast * sym, sym_link * type, initList * ilist)
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
{
ast *rast;
ast *iexpr;
/* if character pointer */
if (IS_CHAR (type->next))
- if ((rast = createIvalCharPtr (sym, type, iexpr)))
+ if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
return rast;
return newNode ('=', sym, iexpr);
/* createIval - generates code for initial value */
/*-----------------------------------------------------------------*/
static ast *
-createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
{
ast *rast = NULL;
/* if structure then */
if (IS_STRUCT (type))
- rast = createIvalStruct (sym, type, ilist);
+ rast = createIvalStruct (sym, type, ilist, rootValue);
else
/* if this is a pointer */
if (IS_PTR (type))
- rast = createIvalPtr (sym, type, ilist);
+ rast = createIvalPtr (sym, type, ilist, rootValue);
else
/* if this is an array */
if (IS_ARRAY (type))
- rast = createIvalArray (sym, type, ilist);
+ rast = createIvalArray (sym, type, ilist, rootValue);
else
/* if type is SPECIFIER */
if (IS_SPEC (type))
/* initAggregates - initialises aggregate variables with initv */
/*-----------------------------------------------------------------*/
ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
- return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
+ ast *newAst = newAst_VALUE (symbolVal (sym));
+ return createIval (newAst, sym->type, ival, wid, newAst);
}
/*-----------------------------------------------------------------*/
/* 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;
}
#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)
/* 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)
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;
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;
static int
isBitAndPow2 (ast * tree)
{
- int p2;
-
/* if this is not a bit and */
if (!IS_BITAND (tree))
return -1;
if (!IS_AST_LIT_VALUE (tree->right))
return -1;
- if (AST_LIT_VALUE (tree->right) == 1)
- return 0;
- p2 = powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
- if (!p2)
- return -1;
-
- return p2;
+ return powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
}
/*-----------------------------------------------------------------*/
ast *
optimizeGetWord (ast * tree, RESULT_TYPE resultType)
{
- unsigned int i;
+ unsigned int i = 0;
ast * expr;
ast * count = NULL;
return;
/*------------------------------------------------------------------*/
/*----------------------------*/
- /* compliment */
+ /* complement */
/*----------------------------*/
case '~':
fprintf(outfile,"COMPL (%p) type (",tree);