static ast *createIvalCharPtr (ast *, sym_link *, ast *);
static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
+ast *optimizeSWAP (ast *);
ast *optimizeGetHbit (ast *);
ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
return tree;
}
+/*-----------------------------------------------------------------*/
+/* removePreIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*++s += 3" -> "*++s = *++s + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePreIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->right)
+ tree=tree->right;
+ }
+
+ tree->left=removePreIncDecOps(tree->left);
+ tree->right=removePreIncDecOps(tree->right);
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePostIncDecOps: remove for side effects in *_ASSIGN's */
+/* "*s++ += 3" -> "*s++ = *s++ + 3" */
+/*-----------------------------------------------------------------*/
+ast *removePostIncDecOps (ast * tree) {
+
+ // traverse the tree and remove pre-inc/dec ops
+
+ if (!tree)
+ return NULL;
+
+ if (tree->type == EX_OP &&
+ (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+ if (tree->left)
+ tree=tree->left;
+ }
+
+ tree->left=removePostIncDecOps(tree->left);
+ tree->right=removePostIncDecOps(tree->right);
+
+ return tree;
+}
+
/*-----------------------------------------------------------------*/
/* hasSEFcalls - returns TRUE if tree has a function call */
/*-----------------------------------------------------------------*/
/* to the array element */
char *s = SPEC_CVAL (iexpr->etype).v_char;
int i = 0;
+ int size = getSize (iexpr->ftype);
- while (*s)
+ for (i=0;i<size;i++)
{
rast = newNode (NULLOP,
rast,
newNode ('[', sym,
newAst_VALUE (valueFromLit ((float) i))),
newAst_VALUE (valueFromLit (*s))));
- i++;
s++;
}
- rast = newNode (NULLOP,
- rast,
- newNode ('=',
- newNode ('[', sym,
- newAst_VALUE (valueFromLit ((float) i))),
- newAst_VALUE (valueFromLit (*s))));
// now WE don't need iexpr's symbol anymore
freeStringSymbol(AST_SYMBOL(iexpr));
static int charLbl = 0;
symbol *sym;
set *sp;
+ int size;
// have we heard this before?
for (sp=statsg->syms; sp; sp=sp->next) {
sym=sp->item;
- if (sym->isstrlit &&
- !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) {
+ size = getSize (sym->type);
+ if (sym->isstrlit && size == getSize (val->type) &&
+ !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
// yes, this is old news. Don't publish it again.
sym->isstrlit++; // but raise the usage count
return symbolVal(sym);
return TRUE;
/*------------------------------------------------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP:
case DEC_OP:
/* sure we are not sym is not modified */
case RRC:
case RLC:
case GETHBIT:
+ case SWAP:
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
return FALSE;
case '?':
case ':':
case SIZEOF: /* evaluate wihout code generation */
+
+ if (IS_AST_SYM_VALUE (pbody->left) &&
+ isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+ return FALSE;
+
+ if (IS_AST_SYM_VALUE (pbody->right) &&
+ isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+ return FALSE;
return isConformingBody (pbody->left, sym, body) &&
isConformingBody (pbody->right, sym, body);
/* adjust the storage class */
switch (DCL_TYPE(tree->left->ftype)) {
case POINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
break;
case FPOINTER:
SPEC_SCLS(TETYPE(tree)) = S_XDATA;
SPEC_SCLS(TETYPE(tree)) = S_CODE;
break;
case GPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
break;
case PPOINTER:
SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
break;
case UPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
case ARRAY:
case FUNCTION:
break;
}
+ /* This breaks with extern declarations, bitfields, and perhaps other */
+ /* cases (gcse). Let's leave this optimization disabled for now and */
+ /* ponder if there's a safe way to do this. -- EEP */
+ #if 0
if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
&& SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
{
tree->left = NULL;
tree->right = NULL;
}
-
+ #endif
+
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* increment operator unary so left only */
+ case INC_OP:
case DEC_OP:
{
sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_REGISTER)
+ if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
{
werror (E_ILLEGAL_ADDR, "address of register variable");
goto errorTreeReturn;
werror (E_LVALUE_REQUIRED, "address of");
goto errorTreeReturn;
}
- if (SPEC_SCLS (tree->left->etype) == S_CODE)
+ if (!LETYPE (tree))
+ DCL_TYPE (p) = POINTER;
+ else if (SPEC_SCLS (tree->left->etype) == S_CODE)
DCL_TYPE (p) = CPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
DCL_TYPE (p) = FPOINTER;
ast *wtree = optimizeRRCRLC (tree);
if (wtree != tree)
return decorateType (wtree);
+
+ wtree = optimizeSWAP (tree);
+ if (wtree != tree)
+ return decorateType (wtree);
+
// fall through
}
}
TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
TETYPE (tree) = getSpec (TTYPE (tree));
+ /* adjust the storage class */
+ switch (DCL_TYPE(tree->left->ftype)) {
+ case POINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_DATA;
+ break;
+ case FPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+ break;
+ case CPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_CODE;
+ break;
+ case GPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
+ case PPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+ break;
+ case IPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+ break;
+ case EEPPOINTER:
+ SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
+ break;
+ case UPOINTER:
+ SPEC_SCLS (TETYPE (tree)) = 0;
+ break;
+ case ARRAY:
+ case FUNCTION:
+ break;
+ }
return tree;
}
/* if unary plus */
if (!tree->right)
{
- if (!IS_INTEGRAL (LTYPE (tree)))
+ if (!IS_ARITHMETIC (LTYPE (tree)))
{
werror (E_UNARY_OP, '+');
goto errorTreeReturn;
/*----------------------------*/
case RRC:
case RLC:
+ case SWAP:
TTYPE (tree) = LTYPE (tree);
TETYPE (tree) = LETYPE (tree);
return tree;
}
}
LRVAL (tree) = RRVAL (tree) = 1;
- if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree)))
- {
- COPYTYPE (TTYPE (tree), TETYPE (tree), RTYPE (tree));
- }
- else
- {
- COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
- }
+ TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+ if (IS_LITERAL (TTYPE (tree)))
+ SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
return tree;
/*------------------------------------------------------------------*/
tree->opval.val = valCastLiteral (
LTYPE (tree),
element->offset
- + floatFromVal (valFromType (RETYPE (tree->right->left->left)))
+ + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
);
TTYPE (tree) = tree->opval.val->type;
sym->cdef = 1;
sym->isref = 1;
SPEC_STAT (sym->etype) = 1;
- SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree)));
+ SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
SPEC_ABSA(sym->etype) = 1;
addSym (SymbolTab, sym, sym->name, 0, 0, 0);
allocGlobal (sym);
tree->type = EX_VALUE;
tree->opval.val =
valCastLiteral (LTYPE (tree),
- floatFromVal (valFromType (RETYPE (tree))));
+ floatFromVal (valFromType (RTYPE (tree))));
TTYPE (tree) = tree->opval.val->type;
tree->left = NULL;
tree->right = NULL;
IS_LITERAL (LTYPE (tree)))
{
tree->type = EX_VALUE;
- tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
- valFromType (RETYPE (tree)),
+ tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+ valFromType (RTYPE (tree)),
tree->opval.op);
tree->right = tree->left = NULL;
TETYPE (tree) = getSpec (TTYPE (tree) =
if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
{
werror (E_COMPARE_OP);
- fprintf (stderr, "comparring type ");
+ fprintf (stderr, "comparing type ");
printTypeChain (LTYPE (tree), stderr);
fprintf (stderr, "to type ");
printTypeChain (RTYPE (tree), stderr);
TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
- werror (E_CODE_WRITE, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
if (LRVAL (tree))
{
- werror (E_LVALUE_REQUIRED, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+ werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
goto errorTreeReturn;
}
LLVAL (tree) = 1;
if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
(j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
return tree;
+
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+ return tree;
return decorateType (newNode (GETHBIT, tree->left->left, NULL));
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext0;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
}
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext1;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext2;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
return root;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
return root;
}
+/*-----------------------------------------------------------------*/
+/* optimizeSWAP :- optimize for nibble/byte/word swaps */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeSWAP (ast * root)
+{
+ /* will look for trees of the form
+ (?expr << 4) | (?expr >> 4) or
+ (?expr >> 4) | (?expr << 4) will make that
+ into a SWAP : operation ..
+ note : by 4 I mean (number of bits required to hold the
+ variable /2 ) */
+ /* if the root operations is not a | operation the not */
+ if (!IS_BITOR (root))
+ return root;
+
+ /* (?expr << 4) | (?expr >> 4) */
+ if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
+ || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
+ {
+
+ if (!SPEC_USIGN (TETYPE (root->left->left)))
+ return root;
+
+ if (!IS_AST_LIT_VALUE (root->left->right) ||
+ !IS_AST_LIT_VALUE (root->right->right))
+ return root;
+
+ /* make sure it is the same expression */
+ if (!isAstEqual (root->left->left,
+ root->right->left))
+ return root;
+
+ if (AST_LIT_VALUE (root->left->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ if (AST_LIT_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ /* make sure the port supports SWAP */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
+ return root;
+
+ /* found it : create the AST */
+ return newNode (SWAP, root->left->left, NULL);
+ }
+
+
+ /* not found return root */
+ return root;
+}
+
/*-----------------------------------------------------------------*/
/* optimizeCompare - otimizes compares for bit variables */
/*-----------------------------------------------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP:
+ if (tree->left)
+ fprintf(outfile,"post-");
+ else
+ fprintf(outfile,"pre-");
fprintf(outfile,"INC_OP (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->left,outfile,indent+2); /* postincrement case */
+ ast_print(tree->right,outfile,indent+2); /* preincrement case */
return ;
case DEC_OP:
+ if (tree->left)
+ fprintf(outfile,"post-");
+ else
+ fprintf(outfile,"pre-");
fprintf(outfile,"DEC_OP (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
fprintf(outfile,")\n");
- ast_print(tree->left,outfile,indent+2);
+ ast_print(tree->left,outfile,indent+2); /* postdecrement case */
+ ast_print(tree->right,outfile,indent+2); /* predecrement case */
return ;
/*------------------------------------------------------------------*/
fprintf(outfile,")\n");
ast_print(tree->left,outfile,indent+2);
return ;
+ case SWAP:
+ fprintf(outfile,"SWAP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
case GETHBIT:
fprintf(outfile,"GETHBIT (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
fprintf(outfile,"FOR LOOP BODY \n");
ast_print(tree->left,outfile,indent+2);
return ;
+ case CRITICAL:
+ fprintf(outfile,"CRITICAL (%p) \n",tree);
+ ast_print(tree->left,outfile,indent+2);
default:
return ;
}
{
ast_print(t,stdout,0);
}
+
+
+
+/*-----------------------------------------------------------------*/
+/* astErrors : returns non-zero if errors present in tree */
+/*-----------------------------------------------------------------*/
+int astErrors(ast *t)
+{
+ int errors=0;
+
+ if (t)
+ {
+ if (t->isError)
+ errors++;
+
+ if (t->type == EX_VALUE
+ && t->opval.val->sym
+ && t->opval.val->sym->undefined)
+ errors++;
+
+ errors += astErrors(t->left);
+ errors += astErrors(t->right);
+ }
+
+ return errors;
+}