1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
545 /* if this is a label resolve it from the labelTab */
546 if (IS_AST_VALUE (tree) &&
547 tree->opval.val->sym &&
548 tree->opval.val->sym->islbl)
550 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
551 tree->opval.val->sym->name);
554 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
555 tree->opval.val->sym->name);
557 tree->opval.val->sym = csym;
559 goto resolveChildren;
562 /* do only for leafs */
563 if (IS_AST_VALUE (tree) &&
564 tree->opval.val->sym &&
565 !tree->opval.val->sym->implicit)
567 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
569 /* if found in the symbol table & they are not the same */
570 if (csym && tree->opval.val->sym != csym)
572 tree->opval.val->sym = csym;
573 tree->opval.val->type = csym->type;
574 tree->opval.val->etype = csym->etype;
577 /* if not found in the symbol table */
578 /* mark it as undefined & assume it */
579 /* is an integer in data space */
580 if (!csym && !tree->opval.val->sym->implicit)
582 /* if this is a function name then */
583 /* mark it as returning an int */
586 tree->opval.val->sym->type = newLink (DECLARATOR);
587 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
588 tree->opval.val->sym->type->next =
589 tree->opval.val->sym->etype = newIntLink ();
590 tree->opval.val->etype = tree->opval.val->etype;
591 tree->opval.val->type = tree->opval.val->sym->type;
592 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
593 tree->opval.val->sym->name);
594 //tree->opval.val->sym->undefined = 1;
595 allocVariables (tree->opval.val->sym);
599 tree->opval.val->sym->undefined = 1;
600 tree->opval.val->type =
601 tree->opval.val->etype = newIntLink ();
602 tree->opval.val->sym->type =
603 tree->opval.val->sym->etype = newIntLink ();
609 resolveSymbols (tree->left);
610 resolveSymbols (tree->right);
615 /*------------------------------------------------------------------------*/
616 /* setAstFileLine - walks a ast tree & sets the file name and line number */
617 /*------------------------------------------------------------------------*/
618 int setAstFileLine (ast * tree, char *filename, int lineno)
623 tree->filename = filename;
624 tree->lineno = lineno;
625 setAstFileLine (tree->left, filename, lineno);
626 setAstFileLine (tree->right, filename, lineno);
630 /*-----------------------------------------------------------------*/
631 /* funcOfType :- function of type with name */
632 /*-----------------------------------------------------------------*/
634 funcOfType (char *name, sym_link * type, sym_link * argType,
638 /* create the symbol */
639 sym = newSymbol (name, 0);
641 /* setup return value */
642 sym->type = newLink (DECLARATOR);
643 DCL_TYPE (sym->type) = FUNCTION;
644 sym->type->next = copyLinkChain (type);
645 sym->etype = getSpec (sym->type);
646 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
648 /* if arguments required */
652 args = FUNC_ARGS(sym->type) = newValue ();
656 args->type = copyLinkChain (argType);
657 args->etype = getSpec (args->type);
658 SPEC_EXTR(args->etype)=1;
661 args = args->next = newValue ();
668 allocVariables (sym);
673 /*-----------------------------------------------------------------*/
674 /* funcOfTypeVarg :- function of type with name and argtype */
675 /*-----------------------------------------------------------------*/
677 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
682 /* create the symbol */
683 sym = newSymbol (name, 0);
685 /* setup return value */
686 sym->type = newLink (DECLARATOR);
687 DCL_TYPE (sym->type) = FUNCTION;
688 sym->type->next = typeFromStr(rtype);
689 sym->etype = getSpec (sym->type);
691 /* if arguments required */
694 args = FUNC_ARGS(sym->type) = newValue ();
696 for ( i = 0 ; i < nArgs ; i++ ) {
697 args->type = typeFromStr(atypes[i]);
698 args->etype = getSpec (args->type);
699 SPEC_EXTR(args->etype)=1;
700 if ((i + 1) == nArgs) break;
701 args = args->next = newValue ();
708 allocVariables (sym);
713 /*-----------------------------------------------------------------*/
714 /* reverseParms - will reverse a parameter tree */
715 /*-----------------------------------------------------------------*/
717 reverseParms (ast * ptree)
723 /* top down if we find a nonParm tree then quit */
724 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
726 /* The various functions expect the parameter tree to be right heavy. */
727 /* Rotate the tree to be left heavy so that after reversal it is */
728 /* right heavy again. */
729 while ((ttree = ptree->right) && ttree->type == EX_OP &&
730 ttree->opval.op == PARAM)
732 ptree->right = ttree->right;
733 ttree->right = ttree->left;
734 ttree->left = ptree->left;
740 ptree->left = ptree->right;
741 ptree->right = ttree;
743 reverseParms (ptree->left);
744 reverseParms (ptree->right);
750 /*-----------------------------------------------------------------*/
751 /* processParms - makes sure the parameters are okay and do some */
752 /* processing with them */
753 /*-----------------------------------------------------------------*/
755 processParms (ast *func,
758 int *parmNumber, /* unused, although updated */
761 RESULT_TYPE resultType;
764 /* if none of them exist */
765 if (!defParm && !*actParm)
770 if (getenv("DEBUG_SANITY"))
772 fprintf (stderr, "processParms: %s ", defParm->name);
774 /* make sure the type is complete and sane */
775 checkTypeSanity(defParm->etype, defParm->name);
778 if (IS_CODEPTR (func->ftype))
779 functype = func->ftype->next;
781 functype = func->ftype;
783 /* if the function is being called via a pointer & */
784 /* it has not been defined reentrant then we cannot */
785 /* have parameters */
786 /* PIC16 port can... */
787 if (!TARGET_IS_PIC16)
789 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
791 werror (E_NONRENT_ARGS);
797 /* if defined parameters ended but actual parameters */
798 /* exist and this is not defined as a variable arg */
799 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
801 werror (E_TOO_MANY_PARMS);
805 /* if defined parameters present but no actual parameters */
806 if (defParm && !*actParm)
808 werror (E_TOO_FEW_PARMS);
812 /* if this is a PARAM node then match left & right */
813 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
815 (*actParm)->decorated = 1;
816 return (processParms (func, defParm,
817 &(*actParm)->left, parmNumber, FALSE) ||
818 processParms (func, defParm ? defParm->next : NULL,
819 &(*actParm)->right, parmNumber, rightmost));
821 else if (defParm) /* not vararg */
823 /* If we have found a value node by following only right-hand links,
824 * then we know that there are no more values after us.
826 * Therefore, if there are more defined parameters, the caller didn't
829 if (rightmost && defParm->next)
831 werror (E_TOO_FEW_PARMS);
836 /* decorate parameter */
837 resultType = defParm ? getResultTypeFromType (defParm->type) :
839 *actParm = decorateType (*actParm, resultType);
841 if (IS_VOID((*actParm)->ftype))
843 werror (E_VOID_VALUE_USED);
847 /* If this is a varargs function... */
848 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
853 /* don't perform integer promotion of explicitly typecasted variable arguments
854 * if sdcc extensions are enabled */
855 if (options.std_sdcc &&
856 (IS_CAST_OP (*actParm) ||
857 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
858 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
860 /* Parameter was explicitly typecast; don't touch it. */
864 ftype = (*actParm)->ftype;
866 /* If it's a char, upcast to int. */
867 if (IS_INTEGRAL (ftype)
868 && (getSize (ftype) < (unsigned) INTSIZE))
870 newType = newAst_LINK(INTTYPE);
873 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
875 newType = newAst_LINK (copyLinkChain(ftype));
876 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
879 if (IS_AGGREGATE (ftype))
881 newType = newAst_LINK (copyLinkChain (ftype));
882 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887 /* cast required; change this op to a cast. */
888 (*actParm)->decorated = 0;
889 *actParm = newNode (CAST, newType, *actParm);
890 (*actParm)->filename = (*actParm)->right->filename;
891 (*actParm)->lineno = (*actParm)->right->lineno;
893 decorateType (*actParm, RESULT_TYPE_NONE);
898 /* if defined parameters ended but actual has not & */
900 if (!defParm && *actParm &&
901 (options.stackAuto || IFFUNC_ISREENT (functype)))
904 resolveSymbols (*actParm);
906 /* the parameter type must be at least castable */
907 if (compareType (defParm->type, (*actParm)->ftype) == 0)
909 werror (E_INCOMPAT_TYPES);
910 printFromToType ((*actParm)->ftype, defParm->type);
914 /* if the parameter is castable then add the cast */
915 if (compareType (defParm->type, (*actParm)->ftype) < 0)
919 resultType = getResultTypeFromType (defParm->etype);
920 pTree = resolveSymbols (copyAst (*actParm));
922 /* now change the current one to a cast */
923 (*actParm)->type = EX_OP;
924 (*actParm)->opval.op = CAST;
925 (*actParm)->left = newAst_LINK (defParm->type);
926 (*actParm)->right = pTree;
927 (*actParm)->decorated = 0; /* force typechecking */
928 decorateType (*actParm, resultType);
931 /* make a copy and change the regparm type to the defined parm */
932 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
933 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
934 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
936 /* if the function is being called via a pointer & */
937 /* this parameter is not passed in registers */
938 /* then the function must be defined reentrant */
939 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
940 !IFFUNC_ISREENT (functype) && !options.stackAuto)
942 werror (E_NONRENT_ARGS);
951 /*-----------------------------------------------------------------*/
952 /* createIvalType - generates ival for basic types */
953 /*-----------------------------------------------------------------*/
955 createIvalType (ast * sym, sym_link * type, initList * ilist)
959 /* if initList is deep */
960 if (ilist && ilist->type == INIT_DEEP)
961 ilist = ilist->init.deep;
964 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
966 iExpr = newAst_VALUE (valueFromLit (0));
967 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
970 /*-----------------------------------------------------------------*/
971 /* createIvalStruct - generates initial value for structures */
972 /*-----------------------------------------------------------------*/
974 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
980 sym_link * etype = getSpec (type);
982 sflds = SPEC_STRUCT (type)->fields;
983 if (ilist && ilist->type != INIT_DEEP)
985 werror (E_INIT_STRUCT, "");
989 iloop = ilist ? ilist->init.deep : NULL;
991 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
993 /* if we have come to end */
994 if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1000 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
1001 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
1002 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
1003 iloop, rast, rootValue)),
1009 if (IS_AST_VALUE (sym))
1010 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1011 W_EXCESS_INITIALIZERS, "struct",
1012 sym->opval.val->sym->name);
1014 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1020 /*-----------------------------------------------------------------*/
1021 /* createIvalArray - generates code for array initialization */
1022 /*-----------------------------------------------------------------*/
1024 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1028 int lcnt = 0, size = 0;
1029 literalList *literalL;
1030 sym_link * etype = getSpec (type);
1032 /* take care of the special case */
1033 /* array of characters can be init */
1035 if (IS_CHAR (type->next))
1036 if ((rast = createIvalCharPtr (sym,
1038 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1041 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1043 /* not the special case */
1044 if (ilist && ilist->type != INIT_DEEP)
1046 werror (E_INIT_STRUCT, "");
1050 iloop = ilist ? ilist->init.deep : NULL;
1051 lcnt = DCL_ELEM (type);
1054 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1059 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
1063 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1065 rast = newNode(ARRAYINIT, aSym, NULL);
1066 rast->values.constlist = literalL;
1068 // Make sure size is set to length of initializer list.
1072 iloop = iloop->next;
1075 if (lcnt && size > lcnt)
1077 // Array size was specified, and we have more initializers than needed.
1078 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1079 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1089 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1094 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1095 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1096 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1098 iloop = (iloop ? iloop->next : NULL);
1100 /* no of elements given and we */
1101 /* have generated for all of them */
1104 // is this a better way? at least it won't crash
1105 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1106 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1113 /* if we have not been given a size */
1114 if (!DCL_ELEM (type))
1116 /* check, if it's a flexible array */
1117 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1118 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1120 DCL_ELEM (type) = size;
1123 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1127 /*-----------------------------------------------------------------*/
1128 /* createIvalCharPtr - generates initial values for char pointers */
1129 /*-----------------------------------------------------------------*/
1131 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1136 /* if this is a pointer & right is a literal array then */
1137 /* just assignment will do */
1138 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1139 SPEC_SCLS (iexpr->etype) == S_CODE)
1140 && IS_ARRAY (iexpr->ftype)))
1141 return newNode ('=', sym, iexpr);
1143 /* left side is an array so we have to assign each element */
1146 /* for each character generate an assignment */
1147 /* to the array element */
1149 unsigned int symsize = getSize (type);
1151 if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
1154 for (i=0; i<symsize; i++)
1156 rast = newNode (NULLOP,
1160 newAst_VALUE (valueFromLit ((float) i))),
1161 newAst_VALUE (valueFromLit (0))));
1164 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1167 if ((IS_LITERAL (iexpr->etype) ||
1168 SPEC_SCLS (iexpr->etype) == S_CODE)
1169 && IS_ARRAY (iexpr->ftype))
1171 /* for each character generate an assignment */
1172 /* to the array element */
1173 char *s = SPEC_CVAL (iexpr->etype).v_char;
1175 unsigned int symsize = getSize (type);
1177 size = getSize (iexpr->ftype);
1178 if (symsize && size>symsize)
1180 if (size>(symsize+1))
1182 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1184 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1190 for (i=0;i<size;i++)
1192 rast = newNode (NULLOP,
1196 newAst_VALUE (valueFromLit ((float) i))),
1197 newAst_VALUE (valueFromLit (*s))));
1201 // now WE don't need iexpr's symbol anymore
1202 freeStringSymbol(AST_SYMBOL(iexpr));
1204 /* if we have not been given a size */
1205 if (!DCL_ELEM (type))
1207 /* check, if it's a flexible array */
1208 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1209 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1211 DCL_ELEM (type) = size;
1214 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1220 /*-----------------------------------------------------------------*/
1221 /* createIvalPtr - generates initial value for pointers */
1222 /*-----------------------------------------------------------------*/
1224 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1230 if (ilist && ilist->type == INIT_DEEP)
1231 ilist = ilist->init.deep;
1233 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1235 /* if character pointer */
1236 if (IS_CHAR (type->next))
1237 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1240 return newNode ('=', sym, iexpr);
1243 /*-----------------------------------------------------------------*/
1244 /* createIval - generates code for initial value */
1245 /*-----------------------------------------------------------------*/
1247 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1251 if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
1254 /* if structure then */
1255 if (IS_STRUCT (type))
1256 rast = createIvalStruct (sym, type, ilist, rootValue);
1258 /* if this is a pointer */
1260 rast = createIvalPtr (sym, type, ilist, rootValue);
1262 /* if this is an array */
1263 if (IS_ARRAY (type))
1264 rast = createIvalArray (sym, type, ilist, rootValue);
1266 /* if type is SPECIFIER */
1268 rast = createIvalType (sym, type, ilist);
1271 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1273 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1276 /*-----------------------------------------------------------------*/
1277 /* initAggregates - initialises aggregate variables with initv */
1278 /*-----------------------------------------------------------------*/
1279 ast * initAggregates (symbol * sym, initList * ival, ast * wid)
1281 ast *newAst = newAst_VALUE (symbolVal (sym));
1282 return createIval (newAst, sym->type, ival, wid, newAst);
1285 /*-----------------------------------------------------------------*/
1286 /* gatherAutoInit - creates assignment expressions for initial */
1288 /*-----------------------------------------------------------------*/
1290 gatherAutoInit (symbol * autoChain)
1297 for (sym = autoChain; sym; sym = sym->next)
1299 /* resolve the symbols in the ival */
1301 resolveIvalSym (sym->ival, sym->type);
1304 /* if we are PIC16 port,
1305 * and this is a static,
1306 * and have initial value,
1307 * and not S_CODE, don't emit in gs segment,
1308 * but allow glue.c:pic16emitRegularMap to put symbol
1309 * in idata section */
1310 if(TARGET_IS_PIC16 &&
1311 IS_STATIC (sym->etype) && sym->ival
1312 && SPEC_SCLS(sym->etype) != S_CODE) {
1313 SPEC_SCLS (sym->etype) = S_DATA;
1318 /* if this is a static variable & has an */
1319 /* initial value the code needs to be lifted */
1320 /* here to the main portion since they can be */
1321 /* initialised only once at the start */
1322 if (IS_STATIC (sym->etype) && sym->ival &&
1323 SPEC_SCLS (sym->etype) != S_CODE)
1327 /* insert the symbol into the symbol table */
1328 /* with level = 0 & name = rname */
1329 newSym = copySymbol (sym);
1330 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1332 /* now lift the code to main */
1333 if (IS_AGGREGATE (sym->type)) {
1334 work = initAggregates (sym, sym->ival, NULL);
1336 if (getNelements(sym->type, sym->ival)>1) {
1337 werrorfl (sym->fileDef, sym->lineDef,
1338 W_EXCESS_INITIALIZERS, "scalar",
1341 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1342 list2expr (sym->ival));
1345 setAstFileLine (work, sym->fileDef, sym->lineDef);
1349 staticAutos = newNode (NULLOP, staticAutos, work);
1356 /* if there is an initial value */
1357 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1359 initList *ilist = sym->ival;
1361 while (ilist->type == INIT_DEEP)
1363 ilist = ilist->init.deep;
1366 /* update lineno for error msg */
1367 filename = sym->fileDef;
1368 lineno = sym->lineDef;
1369 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1371 if (IS_AGGREGATE (sym->type))
1373 work = initAggregates (sym, sym->ival, NULL);
1377 if (getNelements(sym->type, sym->ival)>1)
1379 werrorfl (sym->fileDef, sym->lineDef,
1380 W_EXCESS_INITIALIZERS, "scalar",
1383 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1384 list2expr (sym->ival));
1388 setAstFileLine (work, sym->fileDef, sym->lineDef);
1392 init = newNode (NULLOP, init, work);
1401 /*-----------------------------------------------------------------*/
1402 /* freeStringSymbol - delete a literal string if no more usage */
1403 /*-----------------------------------------------------------------*/
1404 void freeStringSymbol(symbol *sym) {
1405 /* make sure this is a literal string */
1406 assert (sym->isstrlit);
1407 if (--sym->isstrlit == 0) { // lower the usage count
1408 memmap *segment=SPEC_OCLS(sym->etype);
1410 deleteSetItem(&segment->syms, sym);
1415 /*-----------------------------------------------------------------*/
1416 /* stringToSymbol - creates a symbol from a literal string */
1417 /*-----------------------------------------------------------------*/
1419 stringToSymbol (value * val)
1421 char name[SDCC_NAME_MAX + 1];
1422 static int charLbl = 0;
1427 // have we heard this before?
1428 for (sp = statsg->syms; sp; sp = sp->next)
1431 size = getSize (sym->type);
1432 if (sym->isstrlit && size == getSize (val->type) &&
1433 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1435 // yes, this is old news. Don't publish it again.
1436 sym->isstrlit++; // but raise the usage count
1437 return symbolVal (sym);
1441 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1442 sym = newSymbol (name, 0); /* make it @ level 0 */
1443 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1445 /* copy the type from the value passed */
1446 sym->type = copyLinkChain (val->type);
1447 sym->etype = getSpec (sym->type);
1448 /* change to storage class & output class */
1449 SPEC_SCLS (sym->etype) = S_CODE;
1450 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1451 SPEC_STAT (sym->etype) = 1;
1452 /* make the level & block = 0 */
1453 sym->block = sym->level = 0;
1455 /* create an ival */
1456 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1461 allocVariables (sym);
1464 return symbolVal (sym);
1468 /*-----------------------------------------------------------------*/
1469 /* processBlockVars - will go thru the ast looking for block if */
1470 /* a block is found then will allocate the syms */
1471 /* will also gather the auto inits present */
1472 /*-----------------------------------------------------------------*/
1474 processBlockVars (ast * tree, int *stack, int action)
1479 /* if this is a block */
1480 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1484 if (action == ALLOCATE)
1486 *stack += allocVariables (tree->values.sym);
1487 autoInit = gatherAutoInit (tree->values.sym);
1489 /* if there are auto inits then do them */
1491 tree->left = newNode (NULLOP, autoInit, tree->left);
1493 else /* action is deallocate */
1494 deallocLocal (tree->values.sym);
1497 processBlockVars (tree->left, stack, action);
1498 processBlockVars (tree->right, stack, action);
1502 /*-------------------------------------------------------------*/
1503 /* constExprTree - returns TRUE if this tree is a constant */
1505 /*-------------------------------------------------------------*/
1506 bool constExprTree (ast *cexpr) {
1512 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1514 switch (cexpr->type)
1517 if (IS_AST_LIT_VALUE(cexpr)) {
1518 // this is a literal
1521 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1522 // a function's address will never change
1525 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1526 // an array's address will never change
1529 if (IS_AST_SYM_VALUE(cexpr) &&
1530 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1531 // a symbol in code space will never change
1532 // This is only for the 'char *s="hallo"' case and will have to leave
1533 //printf(" code space symbol");
1538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1539 "unexpected link in expression tree\n");
1542 if (cexpr->opval.op==ARRAYINIT) {
1543 // this is a list of literals
1546 if (cexpr->opval.op=='=') {
1547 return constExprTree(cexpr->right);
1549 if (cexpr->opval.op==CAST) {
1550 // cast ignored, maybe we should throw a warning here?
1551 return constExprTree(cexpr->right);
1553 if (cexpr->opval.op=='&') {
1556 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1559 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1564 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1569 /*-----------------------------------------------------------------*/
1570 /* constExprValue - returns the value of a constant expression */
1571 /* or NULL if it is not a constant expression */
1572 /*-----------------------------------------------------------------*/
1574 constExprValue (ast * cexpr, int check)
1576 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1578 /* if this is not a constant then */
1579 if (!IS_LITERAL (cexpr->ftype))
1581 /* then check if this is a literal array
1583 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1584 SPEC_CVAL (cexpr->etype).v_char &&
1585 IS_ARRAY (cexpr->ftype))
1587 value *val = valFromType (cexpr->ftype);
1588 SPEC_SCLS (val->etype) = S_LITERAL;
1589 val->sym = cexpr->opval.val->sym;
1590 val->sym->type = copyLinkChain (cexpr->ftype);
1591 val->sym->etype = getSpec (val->sym->type);
1592 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1596 /* if we are casting a literal value then */
1597 if (IS_AST_OP (cexpr) &&
1598 cexpr->opval.op == CAST &&
1599 IS_LITERAL (cexpr->right->ftype))
1601 return valCastLiteral (cexpr->ftype,
1602 floatFromVal (cexpr->right->opval.val));
1605 if (IS_AST_VALUE (cexpr))
1607 return cexpr->opval.val;
1611 werror (E_CONST_EXPECTED, "found expression");
1616 /* return the value */
1617 if (IS_AST_VALUE (cexpr))
1619 return cexpr->opval.val;
1624 /*-----------------------------------------------------------------*/
1625 /* isLabelInAst - will return true if a given label is found */
1626 /*-----------------------------------------------------------------*/
1628 isLabelInAst (symbol * label, ast * tree)
1630 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1633 if (IS_AST_OP (tree) &&
1634 tree->opval.op == LABEL &&
1635 isSymbolEqual (AST_SYMBOL (tree->left), label))
1638 return isLabelInAst (label, tree->right) &&
1639 isLabelInAst (label, tree->left);
1642 /*-----------------------------------------------------------------*/
1643 /* isLoopCountable - return true if the loop count can be determi- */
1644 /* -ned at compile time . */
1645 /*-----------------------------------------------------------------*/
1647 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1648 symbol ** sym, ast ** init, ast ** end)
1651 /* the loop is considered countable if the following
1652 conditions are true :-
1654 a) initExpr :- <sym> = <const>
1655 b) condExpr :- <sym> < <const1>
1656 c) loopExpr :- <sym> ++
1659 /* first check the initExpr */
1660 if (IS_AST_OP (initExpr) &&
1661 initExpr->opval.op == '=' && /* is assignment */
1662 IS_AST_SYM_VALUE (initExpr->left))
1663 { /* left is a symbol */
1665 *sym = AST_SYMBOL (initExpr->left);
1666 *init = initExpr->right;
1671 /* don't reverse loop with volatile counter */
1672 if (IS_VOLATILE ((*sym)->type))
1675 /* for now the symbol has to be of
1677 if (!IS_INTEGRAL ((*sym)->type))
1680 /* now check condExpr */
1681 if (IS_AST_OP (condExpr))
1684 switch (condExpr->opval.op)
1687 if (IS_AST_SYM_VALUE (condExpr->left) &&
1688 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1689 IS_AST_LIT_VALUE (condExpr->right))
1691 *end = condExpr->right;
1697 if (IS_AST_OP (condExpr->left) &&
1698 condExpr->left->opval.op == '>' &&
1699 IS_AST_LIT_VALUE (condExpr->left->right) &&
1700 IS_AST_SYM_VALUE (condExpr->left->left) &&
1701 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1704 *end = newNode ('+', condExpr->left->right,
1705 newAst_VALUE (constCharVal (1)));
1718 /* check loop expression is of the form <sym>++ */
1719 if (!IS_AST_OP (loopExpr))
1722 /* check if <sym> ++ */
1723 if (loopExpr->opval.op == INC_OP)
1729 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1730 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1737 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1738 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1746 if (loopExpr->opval.op == ADD_ASSIGN)
1749 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1750 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1751 IS_AST_LIT_VALUE (loopExpr->right) &&
1752 AST_ULONG_VALUE (loopExpr->right) != 1)
1760 /*-----------------------------------------------------------------*/
1761 /* astHasVolatile - returns true if ast contains any volatile */
1762 /*-----------------------------------------------------------------*/
1764 astHasVolatile (ast * tree)
1769 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1772 if (IS_AST_OP (tree))
1773 return astHasVolatile (tree->left) ||
1774 astHasVolatile (tree->right);
1779 /*-----------------------------------------------------------------*/
1780 /* astHasPointer - return true if the ast contains any ptr variable */
1781 /*-----------------------------------------------------------------*/
1783 astHasPointer (ast * tree)
1788 if (IS_AST_LINK (tree))
1791 /* if we hit an array expression then check
1792 only the left side */
1793 if (IS_AST_OP (tree) && tree->opval.op == '[')
1794 return astHasPointer (tree->left);
1796 if (IS_AST_VALUE (tree))
1797 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1799 return astHasPointer (tree->left) ||
1800 astHasPointer (tree->right);
1804 /*-----------------------------------------------------------------*/
1805 /* astHasSymbol - return true if the ast has the given symbol */
1806 /*-----------------------------------------------------------------*/
1808 astHasSymbol (ast * tree, symbol * sym)
1810 if (!tree || IS_AST_LINK (tree))
1813 if (IS_AST_VALUE (tree))
1815 if (IS_AST_SYM_VALUE (tree))
1816 return isSymbolEqual (AST_SYMBOL (tree), sym);
1821 return astHasSymbol (tree->left, sym) ||
1822 astHasSymbol (tree->right, sym);
1825 /*-----------------------------------------------------------------*/
1826 /* astHasDeref - return true if the ast has an indirect access */
1827 /*-----------------------------------------------------------------*/
1829 astHasDeref (ast * tree)
1831 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1834 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1836 return astHasDeref (tree->left) || astHasDeref (tree->right);
1839 /*-----------------------------------------------------------------*/
1840 /* isConformingBody - the loop body has to conform to a set of */
1841 /* rules for the loop to be considered reversible read on for rules*/
1842 /*-----------------------------------------------------------------*/
1844 isConformingBody (ast * pbody, symbol * sym, ast * body)
1847 /* we are going to do a pre-order traversal of the
1848 tree && check for the following conditions. (essentially
1849 a set of very shallow tests )
1850 a) the sym passed does not participate in any arithmetic operation
1851 b) There are no function calls
1852 c) all jumps are within the body
1853 d) address of loop control variable not taken
1854 e) if an assignment has a pointer on the left hand side make sure
1855 right does not have loop control variable
1858 /* if we reach the end or a leaf then true */
1859 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1862 /* if anything else is "volatile" */
1863 if (IS_VOLATILE (TETYPE (pbody)))
1866 /* we will walk the body in a pre-order traversal for
1868 switch (pbody->opval.op)
1870 /*------------------------------------------------------------------*/
1872 // if the loopvar is used as an index
1873 /* array op is commutative -- must check both left & right */
1874 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1877 return isConformingBody (pbody->right, sym, body)
1878 && isConformingBody (pbody->left, sym, body);
1880 /*------------------------------------------------------------------*/
1885 /*------------------------------------------------------------------*/
1889 /* sure we are not sym is not modified */
1891 IS_AST_SYM_VALUE (pbody->left) &&
1892 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1896 IS_AST_SYM_VALUE (pbody->right) &&
1897 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1902 /*------------------------------------------------------------------*/
1904 case '*': /* can be unary : if right is null then unary operation */
1909 /* if right is NULL then unary operation */
1910 /*------------------------------------------------------------------*/
1911 /*----------------------------*/
1913 /*----------------------------*/
1916 if (IS_AST_SYM_VALUE (pbody->left) &&
1917 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1920 return isConformingBody (pbody->left, sym, body);
1924 if (astHasSymbol (pbody->left, sym) ||
1925 astHasSymbol (pbody->right, sym))
1930 /*------------------------------------------------------------------*/
1941 if (IS_AST_SYM_VALUE (pbody->left) &&
1942 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1945 if (IS_AST_SYM_VALUE (pbody->right) &&
1946 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1949 return isConformingBody (pbody->left, sym, body) &&
1950 isConformingBody (pbody->right, sym, body);
1958 if (IS_AST_SYM_VALUE (pbody->left) &&
1959 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1961 return isConformingBody (pbody->left, sym, body);
1963 /*------------------------------------------------------------------*/
1975 case SIZEOF: /* evaluate wihout code generation */
1977 if (IS_AST_SYM_VALUE (pbody->left) &&
1978 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1981 if (IS_AST_SYM_VALUE (pbody->right) &&
1982 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1985 return isConformingBody (pbody->left, sym, body) &&
1986 isConformingBody (pbody->right, sym, body);
1988 /*------------------------------------------------------------------*/
1991 /* if left has a pointer & right has loop
1992 control variable then we cannot */
1993 if (astHasPointer (pbody->left) &&
1994 astHasSymbol (pbody->right, sym))
1996 if (astHasVolatile (pbody->left))
1999 if (IS_AST_SYM_VALUE (pbody->left)) {
2000 // if the loopvar has an assignment
2001 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
2003 // if the loopvar is used in another (maybe conditional) block
2004 if (astHasSymbol (pbody->right, sym) &&
2005 (pbody->level >= body->level)) {
2010 if (astHasVolatile (pbody->left))
2013 if (astHasDeref(pbody->right))
2016 return isConformingBody (pbody->left, sym, body) &&
2017 isConformingBody (pbody->right, sym, body);
2028 assert ("Parser should not have generated this\n");
2030 /*------------------------------------------------------------------*/
2031 /*----------------------------*/
2032 /* comma operator */
2033 /*----------------------------*/
2035 return isConformingBody (pbody->left, sym, body) &&
2036 isConformingBody (pbody->right, sym, body);
2038 /*------------------------------------------------------------------*/
2039 /*----------------------------*/
2041 /*----------------------------*/
2043 /* if local & not passed as parameter &
2044 not used to find the function then ok */
2045 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2046 !astHasSymbol (pbody->left, sym))
2052 /*------------------------------------------------------------------*/
2053 /*----------------------------*/
2054 /* return statement */
2055 /*----------------------------*/
2060 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2065 if (astHasSymbol (pbody->left, sym))
2072 return isConformingBody (pbody->left, sym, body) &&
2073 isConformingBody (pbody->right, sym, body);
2076 /*-----------------------------------------------------------------*/
2077 /* isLoopReversible - takes a for loop as input && returns true */
2078 /* if the for loop is reversible. If yes will set the value of */
2079 /* the loop control var & init value & termination value */
2080 /*-----------------------------------------------------------------*/
2082 isLoopReversible (ast * loop, symbol ** loopCntrl,
2083 ast ** init, ast ** end)
2085 /* if option says don't do it then don't */
2086 if (optimize.noLoopReverse)
2088 /* there are several tests to determine this */
2090 /* for loop has to be of the form
2091 for ( <sym> = <const1> ;
2092 [<sym> < <const2>] ;
2093 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2095 if (!isLoopCountable (AST_FOR (loop, initExpr),
2096 AST_FOR (loop, condExpr),
2097 AST_FOR (loop, loopExpr),
2098 loopCntrl, init, end))
2101 /* now do some serious checking on the body of the loop
2104 return isConformingBody (loop->left, *loopCntrl, loop->left);
2108 /*-----------------------------------------------------------------*/
2109 /* replLoopSym - replace the loop sym by loop sym -1 */
2110 /*-----------------------------------------------------------------*/
2112 replLoopSym (ast * body, symbol * sym)
2115 if (!body || IS_AST_LINK (body))
2118 if (IS_AST_SYM_VALUE (body))
2121 if (isSymbolEqual (AST_SYMBOL (body), sym))
2125 body->opval.op = '-';
2126 body->left = newAst_VALUE (symbolVal (sym));
2127 body->right = newAst_VALUE (constCharVal (1));
2135 replLoopSym (body->left, sym);
2136 replLoopSym (body->right, sym);
2140 /*-----------------------------------------------------------------*/
2141 /* reverseLoop - do the actual loop reversal */
2142 /*-----------------------------------------------------------------*/
2144 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2148 /* create the following tree
2153 if (sym) goto for_continue ;
2156 /* put it together piece by piece */
2157 rloop = newNode (NULLOP,
2158 createIf (newAst_VALUE (symbolVal (sym)),
2160 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2163 newAst_VALUE (symbolVal (sym)),
2166 replLoopSym (loop->left, sym);
2167 setAstFileLine (rloop, init->filename, init->lineno);
2169 rloop = newNode (NULLOP,
2171 newAst_VALUE (symbolVal (sym)),
2172 newNode ('-', end, init)),
2173 createLabel (AST_FOR (loop, continueLabel),
2177 newNode (SUB_ASSIGN,
2178 newAst_VALUE (symbolVal (sym)),
2179 newAst_VALUE (constCharVal (1))),
2182 rloop->lineno=init->lineno;
2183 return decorateType (rloop, RESULT_TYPE_NONE);
2187 /*-----------------------------------------------------------------*/
2188 /* searchLitOp - search tree (*ops only) for an ast with literal */
2189 /*-----------------------------------------------------------------*/
2191 searchLitOp (ast *tree, ast **parent, const char *ops)
2195 if (tree && optimize.global_cse)
2197 /* is there a literal operand? */
2199 IS_AST_OP(tree->right) &&
2200 tree->right->right &&
2201 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2203 if (IS_LITERAL (RTYPE (tree->right)) !=
2204 IS_LITERAL (LTYPE (tree->right)))
2206 tree->right->decorated = 0;
2207 tree->decorated = 0;
2211 ret = searchLitOp (tree->right, parent, ops);
2216 IS_AST_OP(tree->left) &&
2217 tree->left->right &&
2218 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2220 if (IS_LITERAL (RTYPE (tree->left)) !=
2221 IS_LITERAL (LTYPE (tree->left)))
2223 tree->left->decorated = 0;
2224 tree->decorated = 0;
2228 ret = searchLitOp (tree->left, parent, ops);
2236 /*-----------------------------------------------------------------*/
2237 /* getResultFromType */
2238 /*-----------------------------------------------------------------*/
2240 getResultTypeFromType (sym_link *type)
2242 /* type = getSpec (type); */
2244 return RESULT_TYPE_BIT;
2245 if (IS_BITFIELD (type))
2247 int blen = SPEC_BLEN (type);
2250 return RESULT_TYPE_BIT;
2252 return RESULT_TYPE_CHAR;
2253 return RESULT_TYPE_INT;
2256 return RESULT_TYPE_CHAR;
2257 if (IS_INT (type) && !IS_LONG (type))
2258 return RESULT_TYPE_INT;
2259 return RESULT_TYPE_OTHER;
2262 /*-----------------------------------------------------------------*/
2263 /* addCast - adds casts to a type specified by RESULT_TYPE */
2264 /*-----------------------------------------------------------------*/
2266 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2269 bool upCasted = FALSE;
2273 case RESULT_TYPE_NONE:
2274 /* if thing smaller than int must be promoted to int */
2276 getSize (tree->etype) >= INTSIZE)
2277 /* promotion not necessary or already an int */
2279 /* char and bits: promote to int */
2280 newLink = newIntLink();
2283 case RESULT_TYPE_BIT:
2285 /* already an int */
2286 bitsForType (tree->etype) >= 16 ||
2287 /* bit to bit operation: don't promote, the code generators
2288 hopefully know everything about promotion rules */
2289 bitsForType (tree->etype) == 1)
2291 newLink = newIntLink();
2294 case RESULT_TYPE_CHAR:
2295 if (IS_CHAR (tree->etype) ||
2296 IS_FLOAT(tree->etype) ||
2297 IS_FIXED(tree->etype))
2299 newLink = newCharLink();
2301 case RESULT_TYPE_INT:
2303 if (getSize (tree->etype) > INTSIZE)
2305 /* warn ("Loosing significant digits"); */
2309 /* char: promote to int */
2311 getSize (tree->etype) >= INTSIZE)
2313 newLink = newIntLink();
2316 case RESULT_TYPE_IFX:
2317 case RESULT_TYPE_OTHER:
2319 /* return type is ifx, long, float: promote char to int */
2320 getSize (tree->etype) >= INTSIZE)
2322 newLink = newIntLink();
2328 tree->decorated = 0;
2329 tree = newNode (CAST, newAst_LINK (newLink), tree);
2330 tree->filename = tree->right->filename;
2331 tree->lineno = tree->right->lineno;
2332 /* keep unsigned type during cast to smaller type,
2333 but not when promoting from char to int */
2335 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2336 return decorateType (tree, resultType);
2339 /*-----------------------------------------------------------------*/
2340 /* resultTypePropagate - decides if resultType can be propagated */
2341 /*-----------------------------------------------------------------*/
2343 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2345 switch (tree->opval.op)
2362 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2363 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2364 return RESULT_TYPE_NONE;
2369 return RESULT_TYPE_NONE;
2373 return RESULT_TYPE_IFX;
2375 return RESULT_TYPE_NONE;
2379 /*-----------------------------------------------------------------*/
2380 /* getLeftResultType - gets type from left branch for propagation */
2381 /*-----------------------------------------------------------------*/
2383 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2385 switch (tree->opval.op)
2389 if (IS_PTR (LTYPE (tree)))
2390 return RESULT_TYPE_NONE;
2392 return getResultTypeFromType (LETYPE (tree));
2394 if (IS_PTR (currFunc->type->next))
2395 return RESULT_TYPE_NONE;
2397 return getResultTypeFromType (currFunc->type->next);
2399 if (!IS_ARRAY (LTYPE (tree)))
2401 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2402 return RESULT_TYPE_CHAR;
2409 /*------------------------------------------------------------------*/
2410 /* gatherImplicitVariables: assigns correct type information to */
2411 /* symbols and values created by replaceAstWithTemporary */
2412 /* and adds the symbols to the declarations list of the */
2413 /* innermost block that contains them */
2414 /*------------------------------------------------------------------*/
2416 gatherImplicitVariables (ast * tree, ast * block)
2421 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2423 /* keep track of containing scope */
2426 if (tree->type == EX_OP && tree->opval.op == '=' &&
2427 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2429 symbol *assignee = tree->left->opval.val->sym;
2431 /* special case for assignment to compiler-generated temporary variable:
2432 compute type of RHS, and set the symbol's type to match */
2433 if (assignee->type == NULL && assignee->infertype) {
2434 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2436 if (dtr != tree->right)
2439 assignee->type = copyLinkChain(TTYPE(dtr));
2440 assignee->etype = getSpec(assignee->type);
2441 SPEC_SCLS (assignee->etype) = S_AUTO;
2442 SPEC_OCLS (assignee->etype) = NULL;
2443 SPEC_EXTR (assignee->etype) = 0;
2444 SPEC_STAT (assignee->etype) = 0;
2445 SPEC_VOLATILE (assignee->etype) = 0;
2446 SPEC_ABSA (assignee->etype) = 0;
2448 wassertl(block != NULL, "implicit variable not contained in block");
2449 wassert(assignee->next == NULL);
2450 if (block != NULL) {
2451 symbol **decl = &(block->values.sym);
2454 wassert(*decl != assignee); /* should not already be in list */
2455 decl = &( (*decl)->next );
2462 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2463 tree->opval.val->type == NULL &&
2464 tree->opval.val->sym &&
2465 tree->opval.val->sym->infertype)
2467 /* fixup type of value for compiler-inferred temporary var */
2468 tree->opval.val->type = tree->opval.val->sym->type;
2469 tree->opval.val->etype = tree->opval.val->sym->etype;
2472 gatherImplicitVariables(tree->left, block);
2473 gatherImplicitVariables(tree->right, block);
2476 /*--------------------------------------------------------------------*/
2477 /* decorateType - compute type for this tree, also does type checking.*/
2478 /* This is done bottom up, since type has to flow upwards. */
2479 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2480 /* result is a char and the operand(s) are int's. */
2481 /* It also does constant folding, and parameter checking. */
2482 /*--------------------------------------------------------------------*/
2484 decorateType (ast * tree, RESULT_TYPE resultType)
2488 RESULT_TYPE resultTypeProp;
2493 /* if already has type then do nothing */
2494 if (tree->decorated)
2497 tree->decorated = 1;
2500 /* print the line */
2501 /* if not block & function */
2502 if (tree->type == EX_OP &&
2503 (tree->opval.op != FUNCTION &&
2504 tree->opval.op != BLOCK &&
2505 tree->opval.op != NULLOP))
2507 filename = tree->filename;
2508 lineno = tree->lineno;
2512 /* if any child is an error | this one is an error do nothing */
2513 if (tree->isError ||
2514 (tree->left && tree->left->isError) ||
2515 (tree->right && tree->right->isError))
2518 /*------------------------------------------------------------------*/
2519 /*----------------------------*/
2520 /* leaf has been reached */
2521 /*----------------------------*/
2522 filename = tree->filename;
2523 lineno = tree->lineno;
2524 /* if this is of type value */
2525 /* just get the type */
2526 if (tree->type == EX_VALUE)
2528 if (IS_LITERAL (tree->opval.val->etype))
2530 /* if this is a character array then declare it */
2531 if (IS_ARRAY (tree->opval.val->type))
2532 tree->opval.val = stringToSymbol (tree->opval.val);
2534 /* otherwise just copy the type information */
2535 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2539 if (tree->opval.val->sym)
2541 /* if the undefined flag is set then give error message */
2542 if (tree->opval.val->sym->undefined)
2544 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2546 TTYPE (tree) = TETYPE (tree) =
2547 tree->opval.val->type = tree->opval.val->sym->type =
2548 tree->opval.val->etype = tree->opval.val->sym->etype =
2549 copyLinkChain (INTTYPE);
2551 else if (tree->opval.val->sym->implicit)
2553 /* if implicit i.e. struct/union member then no type */
2554 TTYPE (tree) = TETYPE (tree) = NULL;
2558 /* copy the type from the value into the ast */
2559 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2561 /* and mark the symbol as referenced */
2562 tree->opval.val->sym->isref = 1;
2566 wassert(0); /* unreached: all values are literals or symbols */
2571 /* if type link for the case of cast */
2572 if (tree->type == EX_LINK)
2574 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2582 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2584 if (tree->left && tree->left->type == EX_OPERAND
2585 && (tree->left->opval.op == INC_OP
2586 || tree->left->opval.op == DEC_OP)
2587 && tree->left->left)
2589 tree->left->right = tree->left->left;
2590 tree->left->left = NULL;
2592 if (tree->right && tree->right->type == EX_OPERAND
2593 && (tree->right->opval.op == INC_OP
2594 || tree->right->opval.op == DEC_OP)
2595 && tree->right->left)
2597 tree->right->right = tree->right->left;
2598 tree->right->left = NULL;
2603 /* Before decorating the left branch we've to decide in dependence
2604 upon tree->opval.op, if resultType can be propagated */
2605 resultTypeProp = resultTypePropagate (tree, resultType);
2607 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2608 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2610 dtl = decorateType (tree->left, resultTypeProp);
2612 /* if an array node, we may need to swap branches */
2613 if (tree->opval.op == '[')
2615 /* determine which is the array & which the index */
2616 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2617 IS_INTEGRAL (LTYPE (tree)))
2619 ast *tempTree = tree->left;
2620 tree->left = tree->right;
2621 tree->right = tempTree;
2625 /* After decorating the left branch there's type information available
2626 in tree->left->?type. If the op is e.g. '=' we extract the type
2627 information from there and propagate it to the right branch. */
2628 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2630 switch (tree->opval.op)
2633 /* delay right side for '?' operator since conditional macro
2634 expansions might rely on this */
2638 /* decorate right side for CALL (parameter list) in processParms();
2639 there is resultType available */
2643 /* don't allocate string if it is a sizeof argument */
2645 dtr = decorateType (tree->right, resultTypeProp);
2649 dtr = decorateType (tree->right, resultTypeProp);
2653 /* this is to take care of situations
2654 when the tree gets rewritten */
2655 if (dtl != tree->left)
2657 if (dtr != tree->right)
2659 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2663 /* depending on type of operator do */
2665 switch (tree->opval.op)
2667 /*------------------------------------------------------------------*/
2668 /*----------------------------*/
2670 /*----------------------------*/
2673 /* first check if this is a array or a pointer */
2674 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2676 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2677 goto errorTreeReturn;
2680 /* check if the type of the idx */
2681 if (!IS_INTEGRAL (RTYPE (tree)))
2683 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2684 goto errorTreeReturn;
2687 /* if the left is an rvalue then error */
2690 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2691 goto errorTreeReturn;
2694 if (IS_LITERAL (RTYPE (tree)))
2696 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2697 int arraySize = DCL_ELEM (LTYPE (tree));
2698 if (arraySize && arrayIndex >= arraySize)
2700 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2705 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2706 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2709 /*------------------------------------------------------------------*/
2710 /*----------------------------*/
2712 /*----------------------------*/
2714 /* if this is not a structure */
2715 if (!IS_STRUCT (LTYPE (tree)))
2717 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2718 goto errorTreeReturn;
2720 TTYPE (tree) = structElemType (LTYPE (tree),
2721 (tree->right->type == EX_VALUE ?
2722 tree->right->opval.val : NULL));
2723 TETYPE (tree) = getSpec (TTYPE (tree));
2726 /*------------------------------------------------------------------*/
2727 /*----------------------------*/
2728 /* struct/union pointer */
2729 /*----------------------------*/
2731 /* if not pointer to a structure */
2732 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2734 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2735 goto errorTreeReturn;
2738 if (!IS_STRUCT (LTYPE (tree)->next))
2740 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2741 goto errorTreeReturn;
2744 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2745 (tree->right->type == EX_VALUE ?
2746 tree->right->opval.val : NULL));
2747 TETYPE (tree) = getSpec (TTYPE (tree));
2749 /* adjust the storage class */
2750 switch (DCL_TYPE(tree->left->ftype)) {
2752 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2755 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2758 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2761 SPEC_SCLS (TETYPE (tree)) = 0;
2764 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2767 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2770 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2773 SPEC_SCLS (TETYPE (tree)) = 0;
2780 /* This breaks with extern declarations, bitfields, and perhaps other */
2781 /* cases (gcse). Let's leave this optimization disabled for now and */
2782 /* ponder if there's a safe way to do this. -- EEP */
2784 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2785 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2787 /* If defined struct type at addr var
2788 then rewrite (&struct var)->member
2790 and define membertype at (addr+offsetof(struct var,member)) temp
2793 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2794 AST_SYMBOL(tree->right));
2796 sym = newSymbol(genSymName (0), 0);
2797 sym->type = TTYPE (tree);
2798 sym->etype = getSpec(sym->type);
2799 sym->lineDef = tree->lineno;
2802 SPEC_STAT (sym->etype) = 1;
2803 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2805 SPEC_ABSA(sym->etype) = 1;
2806 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2809 AST_VALUE (tree) = symbolVal(sym);
2812 tree->type = EX_VALUE;
2820 /*------------------------------------------------------------------*/
2821 /*----------------------------*/
2822 /* ++/-- operation */
2823 /*----------------------------*/
2827 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2828 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2829 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2830 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2839 /*------------------------------------------------------------------*/
2840 /*----------------------------*/
2842 /*----------------------------*/
2843 case '&': /* can be unary */
2844 /* if right is NULL then unary operation */
2845 if (tree->right) /* not an unary operation */
2848 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2850 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2851 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2852 printTypeChain (LTYPE (tree), stderr);
2853 fprintf (stderr, ",");
2854 printTypeChain (RTYPE (tree), stderr);
2855 fprintf (stderr, "\n");
2856 goto errorTreeReturn;
2859 /* if they are both literal */
2860 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2862 tree->type = EX_VALUE;
2863 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2864 valFromType (RETYPE (tree)), '&');
2866 tree->right = tree->left = NULL;
2867 TETYPE (tree) = tree->opval.val->etype;
2868 TTYPE (tree) = tree->opval.val->type;
2872 /* see if this is a GETHBIT operation if yes
2875 ast *otree = optimizeGetHbit (tree, resultType);
2878 return decorateType (otree, RESULT_TYPE_NONE);
2881 /* see if this is a GETABIT operation if yes
2884 ast *otree = optimizeGetAbit (tree, resultType);
2887 return decorateType (otree, RESULT_TYPE_NONE);
2890 /* see if this is a GETBYTE operation if yes
2893 ast *otree = optimizeGetByte (tree, resultType);
2896 return decorateType (otree, RESULT_TYPE_NONE);
2899 /* see if this is a GETWORD operation if yes
2902 ast *otree = optimizeGetWord (tree, resultType);
2905 return decorateType (otree, RESULT_TYPE_NONE);
2908 /* if left is a literal exchange left & right */
2909 if (IS_LITERAL (LTYPE (tree)))
2911 ast *tTree = tree->left;
2912 tree->left = tree->right;
2913 tree->right = tTree;
2916 /* if right is a literal and */
2917 /* we can find a 2nd literal in an and-tree then */
2918 /* rearrange the tree */
2919 if (IS_LITERAL (RTYPE (tree)))
2922 ast *litTree = searchLitOp (tree, &parent, "&");
2926 ast *tTree = litTree->left;
2927 litTree->left = tree->right;
2928 tree->right = tTree;
2929 /* both operands in litTree are literal now */
2930 decorateType (parent, resultType);
2934 LRVAL (tree) = RRVAL (tree) = 1;
2936 TTYPE (tree) = computeType (LTYPE (tree),
2940 TETYPE (tree) = getSpec (TTYPE (tree));
2945 /*------------------------------------------------------------------*/
2946 /*----------------------------*/
2948 /*----------------------------*/
2949 p = newLink (DECLARATOR);
2950 /* if bit field then error */
2951 if (IS_BITVAR (tree->left->etype))
2953 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2954 goto errorTreeReturn;
2957 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2959 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2960 goto errorTreeReturn;
2963 if (IS_FUNC (LTYPE (tree)))
2965 // this ought to be ignored
2966 return (tree->left);
2969 if (IS_LITERAL(LTYPE(tree)))
2971 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2972 goto errorTreeReturn;
2977 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2978 goto errorTreeReturn;
2981 DCL_TYPE (p) = POINTER;
2982 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2983 DCL_TYPE (p) = CPOINTER;
2984 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2985 DCL_TYPE (p) = FPOINTER;
2986 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2987 DCL_TYPE (p) = PPOINTER;
2988 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2989 DCL_TYPE (p) = IPOINTER;
2990 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2991 DCL_TYPE (p) = EEPPOINTER;
2992 else if (SPEC_OCLS(tree->left->etype))
2993 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2995 DCL_TYPE (p) = POINTER;
2997 if (IS_AST_SYM_VALUE (tree->left))
2999 AST_SYMBOL (tree->left)->addrtaken = 1;
3000 AST_SYMBOL (tree->left)->allocreq = 1;
3003 p->next = LTYPE (tree);
3005 TETYPE (tree) = getSpec (TTYPE (tree));
3010 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
3011 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
3013 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
3014 AST_SYMBOL(tree->left->right));
3015 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
3016 valueFromLit(element->offset));
3019 tree->type = EX_VALUE;
3020 tree->values.literalFromCast = 1;
3026 /*------------------------------------------------------------------*/
3027 /*----------------------------*/
3029 /*----------------------------*/
3031 /* if the rewrite succeeds then don't go any further */
3033 ast *wtree = optimizeRRCRLC (tree);
3035 return decorateType (wtree, RESULT_TYPE_NONE);
3037 wtree = optimizeSWAP (tree);
3039 return decorateType (wtree, RESULT_TYPE_NONE);
3042 /* if left is a literal exchange left & right */
3043 if (IS_LITERAL (LTYPE (tree)))
3045 ast *tTree = tree->left;
3046 tree->left = tree->right;
3047 tree->right = tTree;
3050 /* if right is a literal and */
3051 /* we can find a 2nd literal in an or-tree then */
3052 /* rearrange the tree */
3053 if (IS_LITERAL (RTYPE (tree)))
3056 ast *litTree = searchLitOp (tree, &parent, "|");
3060 ast *tTree = litTree->left;
3061 litTree->left = tree->right;
3062 tree->right = tTree;
3063 /* both operands in tTree are literal now */
3064 decorateType (parent, resultType);
3069 /*------------------------------------------------------------------*/
3070 /*----------------------------*/
3072 /*----------------------------*/
3074 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3076 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3077 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3078 printTypeChain (LTYPE (tree), stderr);
3079 fprintf (stderr, ",");
3080 printTypeChain (RTYPE (tree), stderr);
3081 fprintf (stderr, "\n");
3082 goto errorTreeReturn;
3085 /* if they are both literal then rewrite the tree */
3086 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3088 tree->type = EX_VALUE;
3089 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3090 valFromType (RETYPE (tree)),
3092 tree->right = tree->left = NULL;
3093 TETYPE (tree) = tree->opval.val->etype;
3094 TTYPE (tree) = tree->opval.val->type;
3098 /* if left is a literal exchange left & right */
3099 if (IS_LITERAL (LTYPE (tree)))
3101 ast *tTree = tree->left;
3102 tree->left = tree->right;
3103 tree->right = tTree;
3106 /* if right is a literal and */
3107 /* we can find a 2nd literal in a xor-tree then */
3108 /* rearrange the tree */
3109 if (IS_LITERAL (RTYPE (tree)) &&
3110 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3113 ast *litTree = searchLitOp (tree, &parent, "^");
3117 ast *tTree = litTree->left;
3118 litTree->left = tree->right;
3119 tree->right = tTree;
3120 /* both operands in litTree are literal now */
3121 decorateType (parent, resultType);
3125 LRVAL (tree) = RRVAL (tree) = 1;
3127 TTYPE (tree) = computeType (LTYPE (tree),
3131 TETYPE (tree) = getSpec (TTYPE (tree));
3135 /*------------------------------------------------------------------*/
3136 /*----------------------------*/
3138 /*----------------------------*/
3140 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3142 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3143 goto errorTreeReturn;
3145 /* if they are both literal then */
3146 /* rewrite the tree */
3147 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3149 tree->type = EX_VALUE;
3150 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3151 valFromType (RETYPE (tree)));
3152 tree->right = tree->left = NULL;
3153 TETYPE (tree) = getSpec (TTYPE (tree) =
3154 tree->opval.val->type);
3158 LRVAL (tree) = RRVAL (tree) = 1;
3160 TETYPE (tree) = getSpec (TTYPE (tree) =
3161 computeType (LTYPE (tree),
3166 /* if right is a literal and */
3167 /* left is also a division by a literal then */
3168 /* rearrange the tree */
3169 if (IS_LITERAL (RTYPE (tree))
3170 /* avoid infinite loop */
3171 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3174 ast *litTree = searchLitOp (tree, &parent, "/");
3177 if (IS_LITERAL (RTYPE (litTree)))
3181 litTree->right = newNode ('*',
3183 copyAst (tree->right));
3184 litTree->right->filename = tree->filename;
3185 litTree->right->lineno = tree->lineno;
3187 tree->right->opval.val = constCharVal (1);
3188 decorateType (parent, resultType);
3192 /* litTree->left is literal: no gcse possible.
3193 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3194 this would cause an infinit loop. */
3195 parent->decorated = 1;
3196 decorateType (litTree, resultType);
3203 /*------------------------------------------------------------------*/
3204 /*----------------------------*/
3206 /*----------------------------*/
3208 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3210 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3211 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3212 printTypeChain (LTYPE (tree), stderr);
3213 fprintf (stderr, ",");
3214 printTypeChain (RTYPE (tree), stderr);
3215 fprintf (stderr, "\n");
3216 goto errorTreeReturn;
3218 /* if they are both literal then */
3219 /* rewrite the tree */
3220 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3222 tree->type = EX_VALUE;
3223 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3224 valFromType (RETYPE (tree)));
3225 tree->right = tree->left = NULL;
3226 TETYPE (tree) = getSpec (TTYPE (tree) =
3227 tree->opval.val->type);
3230 LRVAL (tree) = RRVAL (tree) = 1;
3231 TETYPE (tree) = getSpec (TTYPE (tree) =
3232 computeType (LTYPE (tree),
3238 /*------------------------------------------------------------------*/
3239 /*----------------------------*/
3240 /* address dereference */
3241 /*----------------------------*/
3242 case '*': /* can be unary : if right is null then unary operation */
3245 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3247 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3248 goto errorTreeReturn;
3253 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3254 goto errorTreeReturn;
3256 if (IS_ADDRESS_OF_OP(tree->left))
3258 /* replace *&obj with obj */
3259 return tree->left->left;
3261 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3262 TETYPE (tree) = getSpec (TTYPE (tree));
3263 /* adjust the storage class */
3264 switch (DCL_TYPE(tree->left->ftype)) {
3266 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3269 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3272 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3275 SPEC_SCLS (TETYPE (tree)) = 0;
3278 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3281 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3284 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3287 SPEC_SCLS (TETYPE (tree)) = 0;
3296 /*------------------------------------------------------------------*/
3297 /*----------------------------*/
3298 /* multiplication */
3299 /*----------------------------*/
3300 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3302 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3303 goto errorTreeReturn;
3306 /* if they are both literal then */
3307 /* rewrite the tree */
3308 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3310 tree->type = EX_VALUE;
3311 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3312 valFromType (RETYPE (tree)));
3313 tree->right = tree->left = NULL;
3314 TETYPE (tree) = getSpec (TTYPE (tree) =
3315 tree->opval.val->type);
3319 /* if left is a literal exchange left & right */
3320 if (IS_LITERAL (LTYPE (tree)))
3322 ast *tTree = tree->left;
3323 tree->left = tree->right;
3324 tree->right = tTree;
3327 /* if right is a literal and */
3328 /* we can find a 2nd literal in a mul-tree then */
3329 /* rearrange the tree */
3330 if (IS_LITERAL (RTYPE (tree)))
3333 ast *litTree = searchLitOp (tree, &parent, "*");
3337 ast *tTree = litTree->left;
3338 litTree->left = tree->right;
3339 tree->right = tTree;
3340 /* both operands in litTree are literal now */
3341 decorateType (parent, resultType);
3345 LRVAL (tree) = RRVAL (tree) = 1;
3346 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3347 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3348 TETYPE (tree) = getSpec (TTYPE (tree) =
3349 computeType (LTYPE (tree),
3356 /*------------------------------------------------------------------*/
3357 /*----------------------------*/
3358 /* unary '+' operator */
3359 /*----------------------------*/
3364 if (!IS_ARITHMETIC (LTYPE (tree)))
3366 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3367 goto errorTreeReturn;
3370 /* if left is a literal then do it */
3371 if (IS_LITERAL (LTYPE (tree)))
3373 tree->type = EX_VALUE;
3374 tree->opval.val = valFromType (LETYPE (tree));
3376 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3380 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3384 /*------------------------------------------------------------------*/
3385 /*----------------------------*/
3387 /*----------------------------*/
3389 /* this is not a unary operation */
3390 /* if both pointers then problem */
3391 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3392 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3394 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3395 goto errorTreeReturn;
3398 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3399 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3401 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3402 goto errorTreeReturn;
3405 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3406 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3408 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3409 goto errorTreeReturn;
3411 /* if they are both literal then */
3412 /* rewrite the tree */
3413 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3415 tree->type = EX_VALUE;
3416 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3417 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3418 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3419 valFromType (RETYPE (tree)));
3420 tree->right = tree->left = NULL;
3421 TETYPE (tree) = getSpec (TTYPE (tree) =
3422 tree->opval.val->type);
3426 /* if the right is a pointer or left is a literal
3427 xchange left & right */
3428 if (IS_ARRAY (RTYPE (tree)) ||
3429 IS_PTR (RTYPE (tree)) ||
3430 IS_LITERAL (LTYPE (tree)))
3432 ast *tTree = tree->left;
3433 tree->left = tree->right;
3434 tree->right = tTree;
3437 /* if right is a literal and */
3438 /* left is also an addition/subtraction with a literal then */
3439 /* rearrange the tree */
3440 if (IS_LITERAL (RTYPE (tree)))
3442 ast *litTree, *parent;
3443 litTree = searchLitOp (tree, &parent, "+-");
3446 if (litTree->opval.op == '+')
3450 ast *tTree = litTree->left;
3451 litTree->left = tree->right;
3452 tree->right = tree->left;
3455 else if (litTree->opval.op == '-')
3457 if (IS_LITERAL (RTYPE (litTree)))
3461 ast *tTree = litTree->left;
3462 litTree->left = tree->right;
3463 tree->right = tTree;
3469 ast *tTree = litTree->right;
3470 litTree->right = tree->right;
3471 tree->right = tTree;
3472 litTree->opval.op = '+';
3473 tree->opval.op = '-';
3476 decorateType (parent, resultType);
3480 LRVAL (tree) = RRVAL (tree) = 1;
3481 /* if the left is a pointer */
3482 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3483 TETYPE (tree) = getSpec (TTYPE (tree) =
3487 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3488 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3489 TETYPE (tree) = getSpec (TTYPE (tree) =
3490 computeType (LTYPE (tree),
3498 /*------------------------------------------------------------------*/
3499 /*----------------------------*/
3501 /*----------------------------*/
3502 case '-': /* can be unary */
3503 /* if right is null then unary */
3507 if (!IS_ARITHMETIC (LTYPE (tree)))
3509 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3510 goto errorTreeReturn;
3513 /* if left is a literal then do it */
3514 if (IS_LITERAL (LTYPE (tree)))
3516 tree->type = EX_VALUE;
3517 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3519 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3522 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3523 TETYPE (tree) = getSpec (TTYPE (tree) =
3524 computeType (LTYPE (tree),
3532 /*------------------------------------------------------------------*/
3533 /*----------------------------*/
3535 /*----------------------------*/
3537 if (!(IS_PTR (LTYPE (tree)) ||
3538 IS_ARRAY (LTYPE (tree)) ||
3539 IS_ARITHMETIC (LTYPE (tree))))
3541 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3542 goto errorTreeReturn;
3545 if (!(IS_PTR (RTYPE (tree)) ||
3546 IS_ARRAY (RTYPE (tree)) ||
3547 IS_ARITHMETIC (RTYPE (tree))))
3549 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3550 goto errorTreeReturn;
3553 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3554 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3555 IS_INTEGRAL (RTYPE (tree))))
3557 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3558 goto errorTreeReturn;
3561 /* if they are both literal then */
3562 /* rewrite the tree */
3563 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3565 tree->type = EX_VALUE;
3566 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3567 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3568 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3569 valFromType (RETYPE (tree)));
3570 tree->right = tree->left = NULL;
3571 TETYPE (tree) = getSpec (TTYPE (tree) =
3572 tree->opval.val->type);
3576 /* if the left & right are equal then zero */
3577 if (isAstEqual (tree->left, tree->right))
3579 tree->type = EX_VALUE;
3580 tree->left = tree->right = NULL;
3581 tree->opval.val = constCharVal (0);
3582 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3586 /* if both of them are pointers or arrays then */
3587 /* the result is going to be an integer */
3588 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3589 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3590 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3592 /* if only the left is a pointer */
3593 /* then result is a pointer */
3594 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3595 TETYPE (tree) = getSpec (TTYPE (tree) =
3599 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3600 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3602 TETYPE (tree) = getSpec (TTYPE (tree) =
3603 computeType (LTYPE (tree),
3609 LRVAL (tree) = RRVAL (tree) = 1;
3611 /* if right is a literal and */
3612 /* left is also an addition/subtraction with a literal then */
3613 /* rearrange the tree */
3614 if (IS_LITERAL (RTYPE (tree))
3615 /* avoid infinite loop */
3616 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3618 ast *litTree, *litParent;
3619 litTree = searchLitOp (tree, &litParent, "+-");
3622 if (litTree->opval.op == '+')
3626 ast *tTree = litTree->left;
3627 litTree->left = litTree->right;
3628 litTree->right = tree->right;
3629 tree->right = tTree;
3630 tree->opval.op = '+';
3631 litTree->opval.op = '-';
3633 else if (litTree->opval.op == '-')
3635 if (IS_LITERAL (RTYPE (litTree)))
3639 ast *tTree = litTree->left;
3640 litTree->left = tree->right;
3641 tree->right = litParent->left;
3642 litParent->left = tTree;
3643 litTree->opval.op = '+';
3645 tree->decorated = 0;
3646 decorateType (tree, resultType);
3652 ast *tTree = litTree->right;
3653 litTree->right = tree->right;
3654 tree->right = tTree;
3657 decorateType (litParent, resultType);
3662 /*------------------------------------------------------------------*/
3663 /*----------------------------*/
3665 /*----------------------------*/
3667 /* can be only integral type */
3668 if (!IS_INTEGRAL (LTYPE (tree)))
3670 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3671 goto errorTreeReturn;
3674 /* if left is a literal then do it */
3675 if (IS_LITERAL (LTYPE (tree)))
3677 tree->type = EX_VALUE;
3678 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3680 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3681 return addCast (tree, resultTypeProp, TRUE);
3684 if (resultType == RESULT_TYPE_BIT &&
3685 IS_UNSIGNED (tree->left->etype) &&
3686 getSize (tree->left->etype) < INTSIZE)
3688 /* promotion rules are responsible for this strange result:
3689 bit -> int -> ~int -> bit
3690 uchar -> int -> ~int -> bit
3692 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3694 /* optimize bit-result, even if we optimize a buggy source */
3695 tree->type = EX_VALUE;
3696 tree->opval.val = constCharVal (1);
3699 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3701 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3704 /*------------------------------------------------------------------*/
3705 /*----------------------------*/
3707 /*----------------------------*/
3709 /* can be pointer */
3710 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3711 !IS_PTR (LTYPE (tree)) &&
3712 !IS_ARRAY (LTYPE (tree)))
3714 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3715 goto errorTreeReturn;
3718 /* if left is another '!' */
3719 if (IS_AST_NOT_OPER (tree->left))
3721 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3723 /* replace double '!!X' by 'X' */
3724 return tree->left->left;
3726 /* remove double '!!X' by 'X ? 1 : 0' */
3727 tree->opval.op = '?';
3728 tree->left = tree->left->left;
3729 tree->right = newNode (':',
3730 newAst_VALUE (constCharVal (1)),
3731 newAst_VALUE (constCharVal (0)));
3732 tree->right->filename = tree->filename;
3733 tree->right->lineno = tree->lineno;
3734 tree->decorated = 0;
3735 return decorateType (tree, resultType);
3738 /* if left is a literal then do it */
3739 if (IS_LITERAL (LTYPE (tree)))
3741 tree->type = EX_VALUE;
3742 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3744 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3748 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3751 /*------------------------------------------------------------------*/
3752 /*----------------------------*/
3754 /*----------------------------*/
3758 TTYPE (tree) = LTYPE (tree);
3759 TETYPE (tree) = LETYPE (tree);
3764 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3768 TTYPE (tree) = TETYPE (tree) = newCharLink();
3772 TTYPE (tree) = TETYPE (tree) = newIntLink();
3777 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3779 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3780 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3781 printTypeChain (LTYPE (tree), stderr);
3782 fprintf (stderr, ",");
3783 printTypeChain (RTYPE (tree), stderr);
3784 fprintf (stderr, "\n");
3785 goto errorTreeReturn;
3788 /* make smaller type only if it's a LEFT_OP */
3789 if (tree->opval.op == LEFT_OP)
3790 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3792 /* if they are both literal then */
3793 /* rewrite the tree */
3794 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3796 tree->type = EX_VALUE;
3797 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3798 valFromType (RETYPE (tree)),
3799 (tree->opval.op == LEFT_OP ? 1 : 0));
3800 tree->right = tree->left = NULL;
3801 TETYPE (tree) = getSpec (TTYPE (tree) =
3802 tree->opval.val->type);
3806 /* see if this is a GETBYTE operation if yes
3809 ast *otree = optimizeGetByte (tree, resultType);
3812 return decorateType (otree, RESULT_TYPE_NONE);
3815 /* see if this is a GETWORD operation if yes
3818 ast *otree = optimizeGetWord (tree, resultType);
3821 return decorateType (otree, RESULT_TYPE_NONE);
3824 LRVAL (tree) = RRVAL (tree) = 1;
3825 if (tree->opval.op == LEFT_OP)
3827 TETYPE (tree) = getSpec (TTYPE (tree) =
3828 computeType (LTYPE (tree),
3835 /* no promotion necessary */
3836 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3837 if (IS_LITERAL (TTYPE (tree)))
3838 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3841 /* if only the right side is a literal & we are
3842 shifting more than size of the left operand then zero */
3843 if (IS_LITERAL (RTYPE (tree)) &&
3844 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3845 (getSize (TETYPE (tree)) * 8))
3847 if (tree->opval.op==LEFT_OP ||
3848 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3850 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3851 (tree->opval.op == LEFT_OP ? "left" : "right"));
3852 tree->type = EX_VALUE;
3853 tree->left = tree->right = NULL;
3854 tree->opval.val = constCharVal (0);
3855 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3862 /*------------------------------------------------------------------*/
3863 /*----------------------------*/
3865 /*----------------------------*/
3866 case CAST: /* change the type */
3867 /* cannot cast to an aggregate type */
3868 if (IS_AGGREGATE (LTYPE (tree)))
3870 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3871 goto errorTreeReturn;
3874 /* make sure the type is complete and sane */
3875 changePointer(LTYPE(tree));
3876 checkTypeSanity(LETYPE(tree), "(cast)");
3879 /* if 'from' and 'to' are the same remove the superfluous cast,
3880 * this helps other optimizations */
3881 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3883 /* mark that the explicit cast has been removed,
3884 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3885 tree->right->values.removedCast = 1;
3889 /* If code memory is read only, then pointers to code memory */
3890 /* implicitly point to constants -- make this explicit */
3892 sym_link *t = LTYPE(tree);
3893 while (t && t->next)
3895 if (IS_CODEPTR(t) && port->mem.code_ro)
3897 if (IS_SPEC(t->next))
3898 SPEC_CONST (t->next) = 1;
3900 DCL_PTR_CONST (t->next) = 1;
3907 /* if the right is a literal replace the tree */
3908 if (IS_LITERAL (RETYPE (tree))) {
3909 if (!IS_PTR (LTYPE (tree))) {
3910 tree->type = EX_VALUE;
3912 valCastLiteral (LTYPE (tree),
3913 floatFromVal (valFromType (RETYPE (tree))));
3916 TTYPE (tree) = tree->opval.val->type;
3917 tree->values.literalFromCast = 1;
3918 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3919 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3920 sym_link *rest = LTYPE(tree)->next;
3921 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3922 TTYPE(tree) = newLink(DECLARATOR);
3923 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3924 TTYPE(tree)->next = rest;
3925 tree->left->opval.lnk = TTYPE(tree);
3928 TTYPE (tree) = LTYPE (tree);
3932 TTYPE (tree) = LTYPE (tree);
3936 #if 0 // this is already checked, now this could be explicit
3937 /* if pointer to struct then check names */
3938 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3939 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3940 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3942 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3943 SPEC_STRUCT(LETYPE(tree))->tag);
3946 if (IS_ADDRESS_OF_OP(tree->right)
3947 && IS_AST_SYM_VALUE (tree->right->left)
3948 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3950 symbol * sym = AST_SYMBOL (tree->right->left);
3951 unsigned int gptype = 0;
3952 unsigned int addr = SPEC_ADDR (sym->etype);
3954 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3955 || TARGET_IS_PIC16) )
3957 switch (SPEC_SCLS (sym->etype))
3960 gptype = GPTYPE_CODE;
3963 gptype = GPTYPE_FAR;
3967 gptype = GPTYPE_NEAR;
3970 gptype = GPTYPE_XSTACK;
3975 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3976 gptype = GPTYPE_NEAR;
3978 addr |= gptype << (8*(GPTRSIZE - 1));
3981 tree->type = EX_VALUE;
3983 valCastLiteral (LTYPE (tree), addr);
3984 TTYPE (tree) = tree->opval.val->type;
3985 TETYPE (tree) = getSpec (TTYPE (tree));
3988 tree->values.literalFromCast = 1;
3992 /* handle offsetof macro: */
3993 /* #define offsetof(TYPE, MEMBER) \ */
3994 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3995 if (IS_ADDRESS_OF_OP(tree->right)
3996 && IS_AST_OP (tree->right->left)
3997 && tree->right->left->opval.op == PTR_OP
3998 && IS_AST_OP (tree->right->left->left)
3999 && tree->right->left->left->opval.op == CAST
4000 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
4002 symbol *element = getStructElement (
4003 SPEC_STRUCT (LETYPE(tree->right->left)),
4004 AST_SYMBOL(tree->right->left->right)
4008 tree->type = EX_VALUE;
4009 tree->opval.val = valCastLiteral (
4012 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
4015 TTYPE (tree) = tree->opval.val->type;
4016 TETYPE (tree) = getSpec (TTYPE (tree));
4023 /* if the right is a literal replace the tree */
4024 if (IS_LITERAL (RETYPE (tree))) {
4026 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
4027 /* rewrite (type *)litaddr
4029 and define type at litaddr temp
4030 (but only if type's storage class is not generic)
4032 ast *newTree = newNode ('&', NULL, NULL);
4035 TTYPE (newTree) = LTYPE (tree);
4036 TETYPE (newTree) = getSpec(LTYPE (tree));
4038 /* define a global symbol at the casted address*/
4039 sym = newSymbol(genSymName (0), 0);
4040 sym->type = LTYPE (tree)->next;
4042 sym->type = newLink (V_VOID);
4043 sym->etype = getSpec(sym->type);
4044 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4045 sym->lineDef = tree->lineno;
4048 SPEC_STAT (sym->etype) = 1;
4049 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4050 SPEC_ABSA(sym->etype) = 1;
4051 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4054 newTree->left = newAst_VALUE(symbolVal(sym));
4055 newTree->left->filename = tree->filename;
4056 newTree->left->lineno = tree->lineno;
4057 LTYPE (newTree) = sym->type;
4058 LETYPE (newTree) = sym->etype;
4059 LLVAL (newTree) = 1;
4060 LRVAL (newTree) = 0;
4061 TLVAL (newTree) = 1;
4065 if (!IS_PTR (LTYPE (tree))) {
4066 tree->type = EX_VALUE;
4068 valCastLiteral (LTYPE (tree),
4069 floatFromVal (valFromType (RTYPE (tree))));
4070 TTYPE (tree) = tree->opval.val->type;
4073 tree->values.literalFromCast = 1;
4074 TETYPE (tree) = getSpec (TTYPE (tree));
4078 TTYPE (tree) = LTYPE (tree);
4082 TETYPE (tree) = getSpec (TTYPE (tree));
4086 /*------------------------------------------------------------------*/
4087 /*----------------------------*/
4088 /* logical &&, || */
4089 /*----------------------------*/
4092 /* each must be arithmetic type or be a pointer */
4093 if (!IS_PTR (LTYPE (tree)) &&
4094 !IS_ARRAY (LTYPE (tree)) &&
4095 !IS_INTEGRAL (LTYPE (tree)))
4097 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4098 goto errorTreeReturn;
4101 if (!IS_PTR (RTYPE (tree)) &&
4102 !IS_ARRAY (RTYPE (tree)) &&
4103 !IS_INTEGRAL (RTYPE (tree)))
4105 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4106 goto errorTreeReturn;
4108 /* if they are both literal then */
4109 /* rewrite the tree */
4110 if (IS_LITERAL (RTYPE (tree)) &&
4111 IS_LITERAL (LTYPE (tree)))
4113 tree->type = EX_VALUE;
4114 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4115 valFromType (RTYPE (tree)),
4117 tree->right = tree->left = NULL;
4118 TETYPE (tree) = getSpec (TTYPE (tree) =
4119 tree->opval.val->type);
4122 LRVAL (tree) = RRVAL (tree) = 1;
4123 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4126 /*------------------------------------------------------------------*/
4127 /*----------------------------*/
4128 /* comparison operators */
4129 /*----------------------------*/
4137 ast *lt = optimizeCompare (tree);
4143 /* if they are pointers they must be castable */
4144 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4146 if (tree->opval.op==EQ_OP &&
4147 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4148 // we cannot cast a gptr to a !gptr: switch the leaves
4149 struct ast *s=tree->left;
4150 tree->left=tree->right;
4153 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4155 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4156 fprintf (stderr, "comparing type ");
4157 printTypeChain (LTYPE (tree), stderr);
4158 fprintf (stderr, "to type ");
4159 printTypeChain (RTYPE (tree), stderr);
4160 fprintf (stderr, "\n");
4161 goto errorTreeReturn;
4164 /* else they should be promotable to one another */
4167 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4168 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4170 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4172 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4173 fprintf (stderr, "comparing type ");
4174 printTypeChain (LTYPE (tree), stderr);
4175 fprintf (stderr, "to type ");
4176 printTypeChain (RTYPE (tree), stderr);
4177 fprintf (stderr, "\n");
4178 goto errorTreeReturn;
4183 CCR_RESULT ccr_result = CCR_OK;
4185 /* if left is integral and right is literal
4186 then check constant range */
4187 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4188 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4189 tree->opval.op, FALSE);
4190 if (ccr_result == CCR_OK &&
4191 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4192 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4193 tree->opval.op, TRUE);
4196 case CCR_ALWAYS_TRUE:
4197 case CCR_ALWAYS_FALSE:
4198 if (!options.lessPedantic)
4199 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4200 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4201 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4208 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4209 if (tree->opval.op == '>' &&
4210 SPEC_USIGN(LETYPE(tree)) &&
4211 IS_LITERAL(RTYPE(tree)) &&
4212 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4214 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4216 /* the parent is an ifx: */
4217 /* if (unsigned value) */
4221 /* (unsigned value) ? 1 : 0 */
4222 tree->opval.op = '?';
4223 tree->right = newNode (':',
4224 newAst_VALUE (constCharVal (1)),
4225 tree->right); /* val 0 */
4226 tree->right->filename = tree->filename;
4227 tree->right->lineno = tree->lineno;
4228 tree->right->left->filename = tree->filename;
4229 tree->right->left->lineno = tree->lineno;
4230 tree->decorated = 0;
4231 return decorateType (tree, resultType);
4234 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4235 if (IS_LITERAL(RTYPE(tree)) &&
4236 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4237 tree->opval.op == EQ_OP &&
4238 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4240 tree->opval.op = '!';
4242 tree->decorated = 0;
4243 return decorateType (tree, resultType);
4246 /* if they are both literal then */
4247 /* rewrite the tree */
4248 if (IS_LITERAL (RTYPE (tree)) &&
4249 IS_LITERAL (LTYPE (tree)))
4251 tree->type = EX_VALUE;
4252 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4253 valFromType (RETYPE (tree)),
4255 tree->right = tree->left = NULL;
4256 TETYPE (tree) = getSpec (TTYPE (tree) =
4257 tree->opval.val->type);
4261 /* if one is 'signed char ' and the other one is 'unsigned char' */
4262 /* it's necessary to promote to int */
4263 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4264 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4266 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4267 if it's possible to use a 'signed char' */
4269 /* is left a 'unsigned char'? */
4270 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4271 /* the value range of a 'unsigned char' is 0...255;
4272 if the actual value is < 128 it can be changed to signed */
4273 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4275 /* now we've got 2 'signed char'! */
4276 SPEC_USIGN (RETYPE (tree)) = 0;
4278 /* same test for the left operand: */
4279 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4280 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4282 SPEC_USIGN (LETYPE (tree)) = 0;
4286 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4287 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4288 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4292 LRVAL (tree) = RRVAL (tree) = 1;
4293 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4295 /* condition transformations */
4297 unsigned transformedOp = 0;
4299 switch (tree->opval.op)
4301 case '<': /* transform (a < b) to !(a >= b) */
4303 transformedOp = GE_OP;
4305 case '>': /* transform (a > b) to !(a <= b) */
4307 transformedOp = LE_OP;
4309 case LE_OP: /* transform (a <= b) to !(a > b) */
4311 transformedOp = '>';
4313 case GE_OP: /* transform (a >= b) to !(a < b) */
4315 transformedOp = '<';
4317 case NE_OP: /* transform (a != b) to !(a == b) */
4319 transformedOp = EQ_OP;
4321 case EQ_OP: /* transform (a == b) to !(a != b) */
4323 transformedOp = NE_OP;
4330 tree->opval.op = transformedOp;
4331 tree->decorated = 0;
4332 tree = newNode ('!', tree, NULL);
4333 tree->filename = tree->left->filename;
4334 tree->lineno = tree->left->lineno;
4335 return decorateType (tree, resultType);
4341 /*------------------------------------------------------------------*/
4342 /*----------------------------*/
4344 /*----------------------------*/
4345 case SIZEOF: /* evaluate wihout code generation */
4346 /* change the type to a integer */
4348 int size = getSize (tree->right->ftype);
4350 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4351 if (!size && !IS_VOID(tree->right->ftype))
4352 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4354 tree->type = EX_VALUE;
4355 tree->opval.val = constVal (buffer);
4356 tree->right = tree->left = NULL;
4357 TETYPE (tree) = getSpec (TTYPE (tree) =
4358 tree->opval.val->type);
4362 /*------------------------------------------------------------------*/
4363 /*----------------------------*/
4365 /*----------------------------*/
4367 /* return typeof enum value */
4368 tree->type = EX_VALUE;
4371 if (IS_SPEC(tree->right->ftype)) {
4372 switch (SPEC_NOUN(tree->right->ftype)) {
4374 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4375 else typeofv = TYPEOF_INT;
4378 typeofv = TYPEOF_FLOAT;
4381 typeofv = TYPEOF_FIXED16X16;
4384 typeofv = TYPEOF_CHAR;
4387 typeofv = TYPEOF_VOID;
4390 typeofv = TYPEOF_STRUCT;
4393 typeofv = TYPEOF_BITFIELD;
4396 typeofv = TYPEOF_BIT;
4399 typeofv = TYPEOF_SBIT;
4405 switch (DCL_TYPE(tree->right->ftype)) {
4407 typeofv = TYPEOF_POINTER;
4410 typeofv = TYPEOF_FPOINTER;
4413 typeofv = TYPEOF_CPOINTER;
4416 typeofv = TYPEOF_GPOINTER;
4419 typeofv = TYPEOF_PPOINTER;
4422 typeofv = TYPEOF_IPOINTER;
4425 typeofv = TYPEOF_ARRAY;
4428 typeofv = TYPEOF_FUNCTION;
4434 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4435 tree->opval.val = constVal (buffer);
4436 tree->right = tree->left = NULL;
4437 TETYPE (tree) = getSpec (TTYPE (tree) =
4438 tree->opval.val->type);
4441 /*------------------------------------------------------------------*/
4442 /*----------------------------*/
4443 /* conditional operator '?' */
4444 /*----------------------------*/
4446 /* the type is value of the colon operator (on the right) */
4447 assert (IS_COLON_OP (tree->right));
4449 /* If already known then replace the tree : optimizer will do it
4450 but faster to do it here. If done before decorating tree->right
4451 this can save generating unused const strings. */
4452 if (IS_LITERAL (LTYPE (tree)))
4454 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4455 return decorateType (tree->right->left, resultTypeProp);
4457 return decorateType (tree->right->right, resultTypeProp);
4460 tree->right = decorateType (tree->right, resultTypeProp);
4462 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4463 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4465 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4466 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4468 if ((valTrue != 0) && (valFalse == 0))
4470 /* assign cond to result */
4471 tree->left->decorated = 0;
4472 return decorateType (tree->left, resultTypeProp);
4474 else if ((valTrue == 0) && (valFalse != 0))
4476 /* assign !cond to result */
4477 tree->opval.op = '!';
4478 tree->decorated = 0;
4480 return decorateType (tree, resultTypeProp);
4484 /* they have the same boolean value, make them equal */
4485 tree->right->left = tree->right->right;
4489 /* if they are equal then replace the tree */
4490 if (isAstEqual (tree->right->left, tree->right->right))
4492 return tree->right->left;
4495 TTYPE (tree) = RTYPE (tree);
4496 TETYPE (tree) = getSpec (TTYPE (tree));
4500 /* if they don't match we have a problem */
4501 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4502 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4504 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4505 goto errorTreeReturn;
4508 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4509 resultType, tree->opval.op);
4510 TETYPE (tree) = getSpec (TTYPE (tree));
4514 #if 0 // assignment operators are converted by the parser
4515 /*------------------------------------------------------------------*/
4516 /*----------------------------*/
4517 /* assignment operators */
4518 /*----------------------------*/
4521 /* for these it must be both must be integral */
4522 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4523 !IS_ARITHMETIC (RTYPE (tree)))
4525 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4526 goto errorTreeReturn;
4529 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4531 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4532 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4536 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4537 goto errorTreeReturn;
4548 /* for these it must be both must be integral */
4549 if (!IS_INTEGRAL (LTYPE (tree)) ||
4550 !IS_INTEGRAL (RTYPE (tree)))
4552 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4553 goto errorTreeReturn;
4556 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4558 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4559 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4563 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4564 goto errorTreeReturn;
4570 /*------------------------------------------------------------------*/
4571 /*----------------------------*/
4573 /*----------------------------*/
4575 if (!(IS_PTR (LTYPE (tree)) ||
4576 IS_ARITHMETIC (LTYPE (tree))))
4578 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4579 goto errorTreeReturn;
4582 if (!(IS_PTR (RTYPE (tree)) ||
4583 IS_ARITHMETIC (RTYPE (tree))))
4585 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4586 goto errorTreeReturn;
4589 TETYPE (tree) = getSpec (TTYPE (tree) =
4590 computeType (LTYPE (tree),
4595 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4596 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4600 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4601 goto errorTreeReturn;
4607 /*------------------------------------------------------------------*/
4608 /*----------------------------*/
4610 /*----------------------------*/
4612 /* this is not a unary operation */
4613 /* if both pointers then problem */
4614 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4616 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4617 goto errorTreeReturn;
4620 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4622 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4623 goto errorTreeReturn;
4626 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4628 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4629 goto errorTreeReturn;
4632 TETYPE (tree) = getSpec (TTYPE (tree) =
4633 computeType (LTYPE (tree),
4638 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4639 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4643 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4644 goto errorTreeReturn;
4647 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4648 tree->opval.op = '=';
4653 /*------------------------------------------------------------------*/
4654 /*----------------------------*/
4655 /* straight assignemnt */
4656 /*----------------------------*/
4658 /* cannot be an aggregate */
4659 if (IS_AGGREGATE (LTYPE (tree)))
4661 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4662 goto errorTreeReturn;
4665 /* they should either match or be castable */
4666 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4668 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4669 printFromToType(RTYPE(tree),LTYPE(tree));
4672 /* if the left side of the tree is of type void
4673 then report error */
4674 if (IS_VOID (LTYPE (tree)))
4676 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4677 printFromToType(RTYPE(tree), LTYPE(tree));
4680 TETYPE (tree) = getSpec (TTYPE (tree) =
4684 if (!tree->initMode ) {
4685 if (IS_CONSTANT(LTYPE(tree)))
4686 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4690 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4691 goto errorTreeReturn;
4696 /*------------------------------------------------------------------*/
4697 /*----------------------------*/
4698 /* comma operator */
4699 /*----------------------------*/
4701 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4704 /*------------------------------------------------------------------*/
4705 /*----------------------------*/
4707 /*----------------------------*/
4710 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4711 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4713 if (tree->left->opval.op == '*' && !tree->left->right)
4714 tree->left = tree->left->left;
4717 /* require a function or pointer to function */
4718 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4720 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4721 goto errorTreeReturn;
4724 /* if there are parms, make sure that
4725 parms are decorate / process / reverse only once */
4727 !tree->right->decorated)
4732 if (IS_FUNCPTR (LTYPE (tree)))
4734 functype = LTYPE (tree)->next;
4735 processFuncPtrArgs (functype);
4738 functype = LTYPE (tree);
4740 if (processParms (tree->left, FUNC_ARGS(functype),
4741 &tree->right, &parmNumber, TRUE))
4743 goto errorTreeReturn;
4746 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4747 !IFFUNC_ISBUILTIN(functype))
4749 reverseParms (tree->right);
4752 TTYPE (tree) = functype->next;
4753 TETYPE (tree) = getSpec (TTYPE (tree));
4757 /*------------------------------------------------------------------*/
4758 /*----------------------------*/
4759 /* return statement */
4760 /*----------------------------*/
4765 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4767 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4768 printFromToType (RTYPE(tree), currFunc->type->next);
4769 goto errorTreeReturn;
4772 if (IS_VOID (currFunc->type->next)
4774 !IS_VOID (RTYPE (tree)))
4776 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4777 goto errorTreeReturn;
4780 /* if there is going to be a casting required then add it */
4781 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4784 decorateType (newNode (CAST,
4785 newAst_LINK (copyLinkChain (currFunc->type->next)),
4795 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4797 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4798 goto errorTreeReturn;
4801 TTYPE (tree) = TETYPE (tree) = NULL;
4804 /*------------------------------------------------------------------*/
4805 /*----------------------------*/
4806 /* switch statement */
4807 /*----------------------------*/
4809 /* the switch value must be an integer */
4810 if (!IS_INTEGRAL (LTYPE (tree)))
4812 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4813 goto errorTreeReturn;
4816 TTYPE (tree) = TETYPE (tree) = NULL;
4819 /*------------------------------------------------------------------*/
4820 /*----------------------------*/
4822 /*----------------------------*/
4824 tree->left = backPatchLabels (tree->left,
4827 TTYPE (tree) = TETYPE (tree) = NULL;
4830 /*------------------------------------------------------------------*/
4831 /*----------------------------*/
4833 /*----------------------------*/
4836 AST_FOR (tree, initExpr) = decorateType (
4837 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4838 AST_FOR (tree, condExpr) = decorateType (
4839 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4840 AST_FOR (tree, loopExpr) = decorateType (
4841 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4843 /* if the for loop is reversible then
4844 reverse it otherwise do what we normally
4850 if (isLoopReversible (tree, &sym, &init, &end))
4851 return reverseLoop (tree, sym, init, end);
4853 return decorateType (createFor (AST_FOR (tree, trueLabel),
4854 AST_FOR (tree, continueLabel),
4855 AST_FOR (tree, falseLabel),
4856 AST_FOR (tree, condLabel),
4857 AST_FOR (tree, initExpr),
4858 AST_FOR (tree, condExpr),
4859 AST_FOR (tree, loopExpr),
4860 tree->left), RESULT_TYPE_NONE);
4863 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4864 "node PARAM shouldn't be processed here");
4865 /* but in processParams() */
4868 TTYPE (tree) = TETYPE (tree) = NULL;
4872 /* some error found this tree will be killed */
4874 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4875 tree->opval.op = NULLOP;
4881 /*-----------------------------------------------------------------*/
4882 /* sizeofOp - processes size of operation */
4883 /*-----------------------------------------------------------------*/
4885 sizeofOp (sym_link * type)
4890 /* make sure the type is complete and sane */
4891 checkTypeSanity(type, "(sizeof)");
4893 /* get the size and convert it to character */
4894 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4895 if (!size && !IS_VOID(type))
4896 werror (E_SIZEOF_INCOMPLETE_TYPE);
4898 /* now convert into value */
4899 return constVal (buff);
4903 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4904 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4905 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4906 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4907 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4908 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4909 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4911 /*-----------------------------------------------------------------*/
4912 /* backPatchLabels - change and or not operators to flow control */
4913 /*-----------------------------------------------------------------*/
4915 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4921 /* while-loops insert a label between the IFX and the condition,
4922 therefore look behind the label too */
4923 if (tree->opval.op == LABEL &&
4925 IS_ANDORNOT (tree->right))
4927 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4931 if (!(IS_ANDORNOT (tree)))
4934 /* if this an and */
4937 static int localLbl = 0;
4940 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4941 localLabel = newSymbol (buffer, NestLevel);
4943 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4945 /* if left is already a IFX then just change the if true label in that */
4946 if (!IS_IFX (tree->left))
4947 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4949 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4950 /* right is a IFX then just join */
4951 if (IS_IFX (tree->right))
4952 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4954 tree->right = createLabel (localLabel, tree->right);
4955 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4957 return newNode (NULLOP, tree->left, tree->right);
4960 /* if this is an or operation */
4963 static int localLbl = 0;
4966 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4967 localLabel = newSymbol (buffer, NestLevel);
4969 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4971 /* if left is already a IFX then just change the if true label in that */
4972 if (!IS_IFX (tree->left))
4973 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4975 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4976 /* right is a IFX then just join */
4977 if (IS_IFX (tree->right))
4978 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4980 tree->right = createLabel (localLabel, tree->right);
4981 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4983 return newNode (NULLOP, tree->left, tree->right);
4989 /* call with exchanged labels */
4990 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4992 /* if left isn't already a IFX */
4993 if (!IS_IFX (tree->left))
4995 tree->left = newNode (IFX, tree->left, NULL);
4996 tree->left->trueLabel = falseLabel;
4997 tree->left->falseLabel = trueLabel;
5004 tree->trueLabel = trueLabel;
5005 tree->falseLabel = falseLabel;
5012 /*-----------------------------------------------------------------*/
5013 /* createBlock - create expression tree for block */
5014 /*-----------------------------------------------------------------*/
5016 createBlock (symbol * decl, ast * body)
5020 /* if the block has nothing */
5024 ex = newNode (BLOCK, NULL, body);
5025 ex->values.sym = decl;
5028 ex->filename = NULL;
5033 /*-----------------------------------------------------------------*/
5034 /* createLabel - creates the expression tree for labels */
5035 /*-----------------------------------------------------------------*/
5037 createLabel (symbol * label, ast * stmnt)
5040 char name[SDCC_NAME_MAX + 1];
5043 /* must create fresh symbol if the symbol name */
5044 /* exists in the symbol table, since there can */
5045 /* be a variable with the same name as the labl */
5046 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5047 (csym->level == label->level))
5048 label = newSymbol (label->name, label->level);
5050 /* change the name before putting it in add _ */
5051 SNPRINTF(name, sizeof(name), "%s", label->name);
5053 /* put the label in the LabelSymbol table */
5054 /* but first check if a label of the same */
5056 if ((csym = findSym (LabelTab, NULL, name)))
5057 werror (E_DUPLICATE_LABEL, label->name);
5059 addSym (LabelTab, label, name, label->level, 0, 0);
5063 label->key = labelKey++;
5064 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5065 rValue->filename = NULL;
5071 /*-----------------------------------------------------------------*/
5072 /* createCase - generates the parsetree for a case statement */
5073 /*-----------------------------------------------------------------*/
5075 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5077 char caseLbl[SDCC_NAME_MAX + 1];
5081 /* if the switch statement does not exist */
5082 /* then case is out of context */
5085 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5089 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5090 /* if not a constant then error */
5091 if (!IS_LITERAL (caseVal->ftype))
5093 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5097 /* if not a integer than error */
5098 if (!IS_INTEGRAL (caseVal->ftype))
5100 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5104 /* find the end of the switch values chain */
5105 if (!(val = swStat->values.switchVals.swVals))
5106 swStat->values.switchVals.swVals = caseVal->opval.val;
5109 /* also order the cases according to value */
5111 int cVal = (int) ulFromVal (caseVal->opval.val);
5112 while (val && (int) ulFromVal (val) < cVal)
5118 /* if we reached the end then */
5121 pval->next = caseVal->opval.val;
5123 else if ((int) ulFromVal (val) == cVal)
5125 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5131 /* we found a value greater than */
5132 /* the current value we must add this */
5133 /* before the value */
5134 caseVal->opval.val->next = val;
5136 /* if this was the first in chain */
5137 if (swStat->values.switchVals.swVals == val)
5138 swStat->values.switchVals.swVals =
5141 pval->next = caseVal->opval.val;
5146 /* create the case label */
5147 SNPRINTF(caseLbl, sizeof(caseLbl),
5149 swStat->values.switchVals.swNum,
5150 (int) ulFromVal (caseVal->opval.val));
5152 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5153 rexpr->filename = 0;
5158 /*-----------------------------------------------------------------*/
5159 /* createDefault - creates the parse tree for the default statement */
5160 /*-----------------------------------------------------------------*/
5162 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5164 char defLbl[SDCC_NAME_MAX + 1];
5166 /* if the switch statement does not exist */
5167 /* then case is out of context */
5170 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5174 if (swStat->values.switchVals.swDefault)
5176 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5181 /* turn on the default flag */
5182 swStat->values.switchVals.swDefault = 1;
5184 /* create the label */
5185 SNPRINTF (defLbl, sizeof(defLbl),
5186 "_default_%d", swStat->values.switchVals.swNum);
5187 return createLabel (newSymbol (defLbl, 0), stmnt);
5190 /*-----------------------------------------------------------------*/
5191 /* createIf - creates the parsetree for the if statement */
5192 /*-----------------------------------------------------------------*/
5194 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5196 static int Lblnum = 0;
5198 symbol *ifTrue, *ifFalse, *ifEnd;
5200 /* if neither exists */
5201 if (!elseBody && !ifBody) {
5202 // if there are no side effects (i++, j() etc)
5203 if (!hasSEFcalls(condAst)) {
5208 /* create the labels */
5209 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5210 ifFalse = newSymbol (buffer, NestLevel);
5211 /* if no else body then end == false */
5216 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5217 ifEnd = newSymbol (buffer, NestLevel);
5220 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5221 ifTrue = newSymbol (buffer, NestLevel);
5225 /* attach the ifTrue label to the top of it body */
5226 ifBody = createLabel (ifTrue, ifBody);
5227 /* attach a goto end to the ifBody if else is present */
5230 ifBody = newNode (NULLOP, ifBody,
5232 newAst_VALUE (symbolVal (ifEnd)),
5234 /* put the elseLabel on the else body */
5235 elseBody = createLabel (ifFalse, elseBody);
5236 /* out the end at the end of the body */
5237 elseBody = newNode (NULLOP,
5239 createLabel (ifEnd, NULL));
5243 ifBody = newNode (NULLOP, ifBody,
5244 createLabel (ifFalse, NULL));
5246 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5247 if (IS_IFX (condAst))
5250 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5252 return newNode (NULLOP, ifTree,
5253 newNode (NULLOP, ifBody, elseBody));
5257 /*-----------------------------------------------------------------*/
5258 /* createDo - creates parse tree for do */
5261 /* _docontinue_n: */
5262 /* condition_expression +-> trueLabel -> _dobody_n */
5264 /* +-> falseLabel-> _dobreak_n */
5266 /*-----------------------------------------------------------------*/
5268 createDo (symbol * trueLabel, symbol * continueLabel,
5269 symbol * falseLabel, ast * condAst, ast * doBody)
5274 /* if the body does not exist then it is simple */
5277 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5278 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5279 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5280 doTree->trueLabel = continueLabel;
5281 doTree->falseLabel = NULL;
5283 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5287 /* otherwise we have a body */
5288 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5290 /* attach the body label to the top */
5291 doBody = createLabel (trueLabel, doBody);
5292 /* attach the continue label to end of body */
5293 doBody = newNode (NULLOP, doBody,
5294 createLabel (continueLabel, NULL));
5296 /* now put the break label at the end */
5297 if (IS_IFX (condAst))
5300 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5302 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5304 /* putting it together */
5305 return newNode (NULLOP, doBody, doTree);
5308 /*-----------------------------------------------------------------*/
5309 /* createFor - creates parse tree for 'for' statement */
5312 /* condExpr +-> trueLabel -> _forbody_n */
5314 /* +-> falseLabel-> _forbreak_n */
5317 /* _forcontinue_n: */
5319 /* goto _forcond_n ; */
5321 /*-----------------------------------------------------------------*/
5323 createFor (symbol * trueLabel, symbol * continueLabel,
5324 symbol * falseLabel, symbol * condLabel,
5325 ast * initExpr, ast * condExpr, ast * loopExpr,
5330 /* if loopexpression not present then we can generate it */
5331 /* the same way as a while */
5333 return newNode (NULLOP, initExpr,
5334 createWhile (trueLabel, continueLabel,
5335 falseLabel, condExpr, forBody));
5336 /* vanilla for statement */
5337 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5339 if (condExpr && !IS_IFX (condExpr))
5340 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5343 /* attach condition label to condition */
5344 condExpr = createLabel (condLabel, condExpr);
5346 /* attach body label to body */
5347 forBody = createLabel (trueLabel, forBody);
5349 /* attach continue to forLoop expression & attach */
5350 /* goto the forcond @ and of loopExpression */
5351 loopExpr = createLabel (continueLabel,
5355 newAst_VALUE (symbolVal (condLabel)),
5357 /* now start putting them together */
5358 forTree = newNode (NULLOP, initExpr, condExpr);
5359 forTree = newNode (NULLOP, forTree, forBody);
5360 forTree = newNode (NULLOP, forTree, loopExpr);
5361 /* finally add the break label */
5362 forTree = newNode (NULLOP, forTree,
5363 createLabel (falseLabel, NULL));
5367 /*-----------------------------------------------------------------*/
5368 /* createWhile - creates parse tree for while statement */
5369 /* the while statement will be created as follows */
5371 /* _while_continue_n: */
5372 /* condition_expression +-> trueLabel -> _while_boby_n */
5374 /* +-> falseLabel -> _while_break_n */
5375 /* _while_body_n: */
5377 /* goto _while_continue_n */
5378 /* _while_break_n: */
5379 /*-----------------------------------------------------------------*/
5381 createWhile (symbol * trueLabel, symbol * continueLabel,
5382 symbol * falseLabel, ast * condExpr, ast * whileBody)
5386 /* put the continue label */
5387 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5388 condExpr = createLabel (continueLabel, condExpr);
5389 condExpr->filename = NULL;
5390 condExpr->lineno = 0;
5392 /* put the body label in front of the body */
5393 whileBody = createLabel (trueLabel, whileBody);
5394 whileBody->filename = NULL;
5395 whileBody->lineno = 0;
5396 /* put a jump to continue at the end of the body */
5397 /* and put break label at the end of the body */
5398 whileBody = newNode (NULLOP,
5401 newAst_VALUE (symbolVal (continueLabel)),
5402 createLabel (falseLabel, NULL)));
5404 /* put it all together */
5405 if (IS_IFX (condExpr))
5406 whileTree = condExpr;
5409 whileTree = newNode (IFX, condExpr, NULL);
5410 /* put the true & false labels in place */
5411 whileTree->trueLabel = trueLabel;
5412 whileTree->falseLabel = falseLabel;
5415 return newNode (NULLOP, whileTree, whileBody);
5418 /*-----------------------------------------------------------------*/
5419 /* isShiftRightLitVal _BitAndLitVal - helper function */
5420 /*-----------------------------------------------------------------*/
5422 isShiftRightLitVal_BitAndLitVal (ast * tree)
5424 /* if this is not a bit and */
5425 if (!IS_BITAND (tree))
5428 /* will look for tree of the form
5429 ( expr >> litval2) & litval1 */
5430 if (!IS_AST_LIT_VALUE (tree->right))
5433 if (!IS_RIGHT_OP (tree->left))
5436 if (!IS_AST_LIT_VALUE (tree->left->right))
5439 return tree->left->left;
5442 /*-----------------------------------------------------------------*/
5443 /* isBitAndPowOf2 - helper function */
5444 /*-----------------------------------------------------------------*/
5446 isBitAndPow2 (ast * tree)
5448 /* if this is not a bit and */
5449 if (!IS_BITAND (tree))
5452 /* will look for tree of the form
5453 ( expr & (1 << litval) */
5454 if (!IS_AST_LIT_VALUE (tree->right))
5457 return powof2 (AST_ULONG_VALUE (tree->right));
5460 /*-----------------------------------------------------------------*/
5461 /* optimizeGetHbit - get highest order bit of the expression */
5462 /*-----------------------------------------------------------------*/
5464 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5469 expr = isShiftRightLitVal_BitAndLitVal(tree);
5472 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5473 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5474 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5477 if (!expr && (resultType == RESULT_TYPE_BIT))
5480 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5486 /* make sure the port supports GETHBIT */
5487 if (port->hasExtBitOp
5488 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5491 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5494 /*-----------------------------------------------------------------*/
5495 /* optimizeGetAbit - get a single bit of the expression */
5496 /*-----------------------------------------------------------------*/
5498 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5503 expr = isShiftRightLitVal_BitAndLitVal(tree);
5506 if (AST_ULONG_VALUE (tree->right) != 1)
5508 count = tree->left->right;
5510 if (!expr && (resultType == RESULT_TYPE_BIT))
5512 int p2 = isBitAndPow2 (tree);
5516 count = newAst_VALUE (valueFromLit (p2));
5522 /* make sure the port supports GETABIT */
5523 if (port->hasExtBitOp
5524 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5527 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5531 /*-----------------------------------------------------------------*/
5532 /* optimizeGetByte - get a byte of the expression */
5533 /*-----------------------------------------------------------------*/
5535 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5541 expr = isShiftRightLitVal_BitAndLitVal(tree);
5544 i = AST_ULONG_VALUE (tree->left->right);
5545 count = tree->left->right;
5546 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5549 if (!expr && resultType == RESULT_TYPE_CHAR)
5551 /* if this is a right shift over a multiple of 8 */
5552 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5554 i = AST_ULONG_VALUE (tree->right);
5555 count = tree->right;
5559 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5562 /* make sure the port supports GETBYTE */
5563 if (port->hasExtBitOp
5564 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5567 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5570 /*-----------------------------------------------------------------*/
5571 /* optimizeGetWord - get two bytes of the expression */
5572 /*-----------------------------------------------------------------*/
5574 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5580 expr = isShiftRightLitVal_BitAndLitVal(tree);
5583 i = AST_ULONG_VALUE (tree->left->right);
5584 count = tree->left->right;
5585 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5588 if (!expr && resultType == RESULT_TYPE_INT)
5590 /* if this is a right shift over a multiple of 8 */
5591 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5593 i = AST_ULONG_VALUE (tree->right);
5594 count = tree->right;
5598 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5601 /* make sure the port supports GETWORD */
5602 if (port->hasExtBitOp
5603 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5606 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5609 /*-----------------------------------------------------------------*/
5610 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5611 /*-----------------------------------------------------------------*/
5613 optimizeRRCRLC (ast * root)
5615 /* will look for trees of the form
5616 (?expr << 1) | (?expr >> 7) or
5617 (?expr >> 7) | (?expr << 1) will make that
5618 into a RLC : operation ..
5620 (?expr >> 1) | (?expr << 7) or
5621 (?expr << 7) | (?expr >> 1) will make that
5622 into a RRC operation
5623 note : by 7 I mean (number of bits required to hold the
5625 /* if the root operation is not a | operation then not */
5626 if (!IS_BITOR (root))
5629 /* I have to think of a better way to match patterns this sucks */
5630 /* that aside let's start looking for the first case : I use a
5631 negative check a lot to improve the efficiency */
5632 /* (?expr << 1) | (?expr >> 7) */
5633 if (IS_LEFT_OP (root->left) &&
5634 IS_RIGHT_OP (root->right))
5637 if (!SPEC_USIGN (TETYPE (root->left->left)))
5640 if (!IS_AST_LIT_VALUE (root->left->right) ||
5641 !IS_AST_LIT_VALUE (root->right->right))
5644 /* make sure it is the same expression */
5645 if (!isAstEqual (root->left->left,
5649 if (AST_ULONG_VALUE (root->left->right) != 1)
5652 if (AST_ULONG_VALUE (root->right->right) !=
5653 (getSize (TTYPE (root->left->left)) * 8 - 1))
5656 /* make sure the port supports RLC */
5657 if (port->hasExtBitOp
5658 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5661 /* whew got the first case : create the AST */
5662 return newNode (RLC, root->left->left, NULL);
5666 /* check for second case */
5667 /* (?expr >> 7) | (?expr << 1) */
5668 if (IS_LEFT_OP (root->right) &&
5669 IS_RIGHT_OP (root->left))
5672 if (!SPEC_USIGN (TETYPE (root->left->left)))
5675 if (!IS_AST_LIT_VALUE (root->left->right) ||
5676 !IS_AST_LIT_VALUE (root->right->right))
5679 /* make sure it is the same symbol */
5680 if (!isAstEqual (root->left->left,
5684 if (AST_ULONG_VALUE (root->right->right) != 1)
5687 if (AST_ULONG_VALUE (root->left->right) !=
5688 (getSize (TTYPE (root->left->left)) * 8 - 1))
5691 /* make sure the port supports RLC */
5692 if (port->hasExtBitOp
5693 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5696 /* whew got the first case : create the AST */
5697 return newNode (RLC, root->left->left, NULL);
5702 /* third case for RRC */
5703 /* (?symbol >> 1) | (?symbol << 7) */
5704 if (IS_LEFT_OP (root->right) &&
5705 IS_RIGHT_OP (root->left))
5708 if (!SPEC_USIGN (TETYPE (root->left->left)))
5711 if (!IS_AST_LIT_VALUE (root->left->right) ||
5712 !IS_AST_LIT_VALUE (root->right->right))
5715 /* make sure it is the same symbol */
5716 if (!isAstEqual (root->left->left,
5720 if (AST_ULONG_VALUE (root->left->right) != 1)
5723 if (AST_ULONG_VALUE (root->right->right) !=
5724 (getSize (TTYPE (root->left->left)) * 8 - 1))
5727 /* make sure the port supports RRC */
5728 if (port->hasExtBitOp
5729 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5732 /* whew got the first case : create the AST */
5733 return newNode (RRC, root->left->left, NULL);
5737 /* fourth and last case for now */
5738 /* (?symbol << 7) | (?symbol >> 1) */
5739 if (IS_RIGHT_OP (root->right) &&
5740 IS_LEFT_OP (root->left))
5743 if (!SPEC_USIGN (TETYPE (root->left->left)))
5746 if (!IS_AST_LIT_VALUE (root->left->right) ||
5747 !IS_AST_LIT_VALUE (root->right->right))
5750 /* make sure it is the same symbol */
5751 if (!isAstEqual (root->left->left,
5755 if (AST_ULONG_VALUE (root->right->right) != 1)
5758 if (AST_ULONG_VALUE (root->left->right) !=
5759 (getSize (TTYPE (root->left->left)) * 8 - 1))
5762 /* make sure the port supports RRC */
5763 if (port->hasExtBitOp
5764 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5767 /* whew got the first case : create the AST */
5768 return newNode (RRC, root->left->left, NULL);
5772 /* not found return root */
5776 /*-----------------------------------------------------------------*/
5777 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5778 /*-----------------------------------------------------------------*/
5780 optimizeSWAP (ast * root)
5782 /* will look for trees of the form
5783 (?expr << 4) | (?expr >> 4) or
5784 (?expr >> 4) | (?expr << 4) will make that
5785 into a SWAP : operation ..
5786 note : by 4 I mean (number of bits required to hold the
5788 /* if the root operation is not a | operation then not */
5789 if (!IS_BITOR (root))
5792 /* (?expr << 4) | (?expr >> 4) */
5793 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5794 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5797 if (!SPEC_USIGN (TETYPE (root->left->left)))
5800 if (!IS_AST_LIT_VALUE (root->left->right) ||
5801 !IS_AST_LIT_VALUE (root->right->right))
5804 /* make sure it is the same expression */
5805 if (!isAstEqual (root->left->left,
5809 if (AST_ULONG_VALUE (root->left->right) !=
5810 (getSize (TTYPE (root->left->left)) * 4))
5813 if (AST_ULONG_VALUE (root->right->right) !=
5814 (getSize (TTYPE (root->left->left)) * 4))
5817 /* make sure the port supports SWAP */
5818 if (port->hasExtBitOp
5819 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5822 /* found it : create the AST */
5823 return newNode (SWAP, root->left->left, NULL);
5827 /* not found return root */
5831 /*-----------------------------------------------------------------*/
5832 /* optimizeCompare - optimizes compares for bit variables */
5833 /*-----------------------------------------------------------------*/
5835 optimizeCompare (ast * root)
5837 ast *optExpr = NULL;
5840 unsigned int litValue;
5842 /* if nothing then return nothing */
5846 /* if not a compare op then do leaves */
5847 if (!IS_COMPARE_OP (root))
5849 root->left = optimizeCompare (root->left);
5850 root->right = optimizeCompare (root->right);
5854 /* if left & right are the same then depending
5855 of the operation do */
5856 if (isAstEqual (root->left, root->right))
5858 switch (root->opval.op)
5863 optExpr = newAst_VALUE (constCharVal (0));
5868 optExpr = newAst_VALUE (constCharVal (1));
5872 return decorateType (optExpr, RESULT_TYPE_NONE);
5875 vleft = (root->left->type == EX_VALUE ?
5876 root->left->opval.val : NULL);
5878 vright = (root->right->type == EX_VALUE ?
5879 root->right->opval.val : NULL);
5881 /* if left is a BITVAR in BITSPACE */
5882 /* and right is a LITERAL then */
5883 /* optimize else do nothing */
5884 if (vleft && vright &&
5885 IS_BITVAR (vleft->etype) &&
5886 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5887 IS_LITERAL (vright->etype))
5890 /* if right side > 1 then comparison may never succeed */
5891 if ((litValue = (int) ulFromVal (vright)) > 1)
5893 werror (W_BAD_COMPARE);
5899 switch (root->opval.op)
5901 case '>': /* bit value greater than 1 cannot be */
5902 werror (W_BAD_COMPARE);
5906 case '<': /* bit value < 1 means 0 */
5908 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5911 case LE_OP: /* bit value <= 1 means no check */
5912 optExpr = newAst_VALUE (vright);
5915 case GE_OP: /* bit value >= 1 means only check for = */
5917 optExpr = newAst_VALUE (vleft);
5922 { /* literal is zero */
5923 switch (root->opval.op)
5925 case '<': /* bit value < 0 cannot be */
5926 werror (W_BAD_COMPARE);
5930 case '>': /* bit value > 0 means 1 */
5932 optExpr = newAst_VALUE (vleft);
5935 case LE_OP: /* bit value <= 0 means no check */
5936 case GE_OP: /* bit value >= 0 means no check */
5937 werror (W_BAD_COMPARE);
5941 case EQ_OP: /* bit == 0 means ! of bit */
5942 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5946 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5947 } /* end-of-if of BITVAR */
5953 /*-----------------------------------------------------------------*/
5954 /* addSymToBlock : adds the symbol to the first block we find */
5955 /*-----------------------------------------------------------------*/
5957 addSymToBlock (symbol * sym, ast * tree)
5959 /* reached end of tree or a leaf */
5960 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5964 if (IS_AST_OP (tree) &&
5965 tree->opval.op == BLOCK)
5968 symbol *lsym = copySymbol (sym);
5970 lsym->next = AST_VALUES (tree, sym);
5971 AST_VALUES (tree, sym) = lsym;
5975 addSymToBlock (sym, tree->left);
5976 addSymToBlock (sym, tree->right);
5979 /*-----------------------------------------------------------------*/
5980 /* processRegParms - do processing for register parameters */
5981 /*-----------------------------------------------------------------*/
5983 processRegParms (value * args, ast * body)
5987 if (IS_REGPARM (args->etype))
5988 addSymToBlock (args->sym, body);
5993 /*-----------------------------------------------------------------*/
5994 /* resetParmKey - resets the operandkeys for the symbols */
5995 /*-----------------------------------------------------------------*/
5996 DEFSETFUNC (resetParmKey)
6007 /*------------------------------------------------------------------*/
6008 /* fixupInlineLabel - change a label in an inlined function so that */
6009 /* it is always unique no matter how many times */
6010 /* the function is inlined. */
6011 /*------------------------------------------------------------------*/
6013 fixupInlineLabel (symbol * sym)
6015 char name[SDCC_NAME_MAX + 1];
6017 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
6018 strcpy (sym->name, name);
6021 /*------------------------------------------------------------------*/
6022 /* copyAstLoc - copy location information (file, line, block, etc.) */
6023 /* from one ast node to another */
6024 /*------------------------------------------------------------------*/
6026 copyAstLoc (ast * dest, ast * src)
6028 dest->filename = src->filename;
6029 dest->lineno = src->lineno;
6030 dest->level = src->level;
6031 dest->block = src->block;
6032 dest->seqPoint = src->seqPoint;
6035 /*-----------------------------------------------------------------*/
6036 /* fixupInline - perform various fixups on an inline function tree */
6037 /* to take into account that it is no longer a */
6038 /* stand-alone function. */
6039 /*-----------------------------------------------------------------*/
6041 fixupInline (ast * tree, int level)
6043 int savedBlockno = currBlockno;
6045 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6049 currBlockno = ++blockNo;
6052 /* Add any declared variables back into the symbol table */
6053 decls = tree->values.sym;
6056 decls->level = level;
6057 decls->block = currBlockno;
6058 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6059 decls = decls->next;
6063 tree->level = level;
6064 tree->block = currBlockno;
6066 /* Update symbols */
6067 if (IS_AST_VALUE (tree) &&
6068 tree->opval.val->sym)
6070 symbol * sym = tree->opval.val->sym;
6073 sym->block = currBlockno;
6076 SYM_SPIL_LOC (sym) = NULL;
6079 /* If the symbol is a label, we need to renumber it */
6081 fixupInlineLabel (sym);
6084 /* Update IFX target labels */
6085 if (tree->type == EX_OP && tree->opval.op == IFX)
6087 if (tree->trueLabel)
6088 fixupInlineLabel (tree->trueLabel);
6089 if (tree->falseLabel)
6090 fixupInlineLabel (tree->falseLabel);
6093 /* Replace RETURN with optional assignment and a GOTO to the end */
6094 /* of the inlined function */
6095 if (tree->type == EX_OP && tree->opval.op == RETURN)
6097 ast * assignTree = NULL;
6100 if (inlineState.retsym && tree->right)
6102 assignTree = newNode ('=',
6103 newAst_VALUE (symbolVal (inlineState.retsym)),
6105 copyAstLoc (assignTree, tree);
6108 gotoTree = newNode (GOTO,
6109 newAst_VALUE (symbolVal (inlineState.retlab)),
6111 copyAstLoc (gotoTree, tree);
6113 tree->opval.op = NULLOP;
6114 tree->left = assignTree;
6115 tree->right = gotoTree;
6118 /* Update any children */
6120 fixupInline (tree->left, level);
6122 fixupInline (tree->right, level);
6124 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6126 symbol * label = tree->left->opval.val->sym;
6128 label->key = labelKey++;
6129 /* Add this label back into the symbol table */
6130 addSym (LabelTab, label, label->name, label->level, 0, 0);
6133 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6136 currBlockno = savedBlockno;
6140 /*-----------------------------------------------------------------*/
6141 /* inlineAddDecl - add a variable declaration to an ast block. It */
6142 /* is also added to the symbol table if addSymTab */
6144 /*-----------------------------------------------------------------*/
6146 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6149 SYM_SPIL_LOC (sym) = NULL;
6153 symbol **decl = &(block->values.sym);
6155 sym->level = block->level;
6156 sym->block = block->block;
6160 if (strcmp ((*decl)->name, sym->name) == 0)
6162 decl = &( (*decl)->next );
6168 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6173 /*-----------------------------------------------------------------*/
6174 /* inlineTempVar - create a temporary variable for inlining */
6175 /*-----------------------------------------------------------------*/
6177 inlineTempVar (sym_link * type, int level)
6181 sym = newSymbol (genSymName(level), level );
6182 sym->type = copyLinkChain (type);
6183 sym->etype = getSpec(sym->type);
6184 SPEC_SCLS (sym->etype) = S_AUTO;
6185 SPEC_OCLS (sym->etype) = NULL;
6186 SPEC_EXTR (sym->etype) = 0;
6187 SPEC_STAT (sym->etype) = 0;
6188 if IS_SPEC (sym->type)
6189 SPEC_VOLATILE (sym->type) = 0;
6191 DCL_PTR_VOLATILE (sym->type) = 0;
6192 SPEC_ABSA (sym->etype) = 0;
6197 /*-----------------------------------------------------------------*/
6198 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6199 /*-----------------------------------------------------------------*/
6201 inlineFindParmRecurse (ast * parms, int *index)
6206 if (parms->type == EX_OP && parms->opval.op == PARAM)
6210 p=inlineFindParmRecurse (parms->left, index);
6213 p=inlineFindParmRecurse (parms->right, index);
6223 /*-----------------------------------------------------------------*/
6224 /* inlineFindParm - search an ast tree of parameters to find one */
6225 /* at a particular index (0=first parameter). */
6226 /* Returns NULL if not found. */
6227 /*-----------------------------------------------------------------*/
6229 inlineFindParm (ast * parms, int index)
6231 return inlineFindParmRecurse (parms, &index);
6234 /*-----------------------------------------------------------------*/
6235 /* expandInlineFuncs - replace calls to inline functions with the */
6236 /* function itself */
6237 /*-----------------------------------------------------------------*/
6239 expandInlineFuncs (ast * tree, ast * block)
6241 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6242 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6244 symbol * func = tree->left->opval.val->sym;
6247 /* The symbol is probably not bound yet, so find the real one */
6248 csym = findSymWithLevel (SymbolTab, func);
6252 /* Is this an inline function that we can inline? */
6253 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6255 symbol * retsym = NULL;
6263 /* Generate a label for the inlined function to branch to */
6264 /* in case it contains a return statement */
6265 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6268 inlineState.retlab = retlab;
6270 /* Build the subtree for the inlined function in the form: */
6271 /* { //inlinetree block */
6272 /* { //inlinetree2 block */
6273 /* inline_function_code; */
6277 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6278 copyAstLoc (temptree, tree);
6279 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6280 copyAstLoc (temptree, tree);
6281 temptree = newNode (BLOCK, NULL, temptree);
6282 copyAstLoc (temptree, tree);
6283 inlinetree2 = temptree;
6284 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6285 copyAstLoc (inlinetree, tree);
6287 /* To pass parameters to the inlined function, we need some */
6288 /* intermediate variables. This avoids scoping problems */
6289 /* when the parameter declaration names are used differently */
6290 /* during the function call. For example, a function */
6291 /* declared as func(int x, int y) but called as func(y,x). */
6292 /* { //inlinetree block */
6293 /* type1 temparg1 = argument1; */
6295 /* typen tempargn = argumentn; */
6296 /* { //inlinetree2 block */
6297 /* type1 param1 = temparg1; */
6299 /* typen paramn = tempargn; */
6300 /* inline_function_code; */
6304 args = FUNC_ARGS (func->type);
6311 ast * passedarg = inlineFindParm (tree->right, argIndex);
6315 werror(E_TOO_FEW_PARMS);
6319 temparg = inlineTempVar (args->sym->type, tree->level+1);
6320 inlineAddDecl (temparg, inlinetree, FALSE);
6322 assigntree = newNode ('=',
6323 newAst_VALUE (symbolVal (temparg)),
6325 assigntree->initMode=1; // tell that assignment is initializer
6326 inlinetree->right = newNode (NULLOP,
6330 parm = copySymbol (args->sym);
6331 inlineAddDecl (parm, inlinetree2, FALSE);
6334 assigntree = newNode ('=',
6335 newAst_VALUE (symbolVal (parm)),
6336 newAst_VALUE (symbolVal (temparg)));
6337 assigntree->initMode=1; // tell that assignment is initializer
6338 inlinetree2->right = newNode (NULLOP,
6340 inlinetree2->right);
6346 /* Handle the return type */
6347 if (!IS_VOID (func->type->next))
6349 /* Create a temporary symbol to hold the return value and */
6350 /* join it with the inlined function using the comma */
6351 /* operator. The fixupInline function will take care of */
6352 /* changing return statements into assignments to retsym. */
6353 /* (parameter passing and return label omitted for clarity) */
6354 /* rettype retsym; */
6356 /* {{inline_function_code}}, retsym */
6358 retsym = inlineTempVar (func->type->next, tree->level);
6359 inlineAddDecl (retsym, block, TRUE);
6361 tree->opval.op = ',';
6362 tree->left = inlinetree;
6363 tree->right = newAst_VALUE (symbolVal (retsym));
6367 tree->opval.op = NULLOP;
6369 tree->right = inlinetree;
6371 inlineState.retsym = retsym;
6373 /* Renumber the various internal counters on the inlined */
6374 /* function's tree nodes and symbols. Add the inlined */
6375 /* function's local variables to the appropriate scope(s). */
6376 /* Convert inlined return statements to an assignment to */
6377 /* retsym (if needed) and a goto retlab. */
6378 fixupInline (inlinetree, inlinetree->level);
6379 inlineState.count++;
6383 /* Recursively continue to search for functions to inline. */
6384 if (IS_AST_OP (tree))
6386 if (tree->opval.op == BLOCK)
6390 expandInlineFuncs (tree->left, block);
6392 expandInlineFuncs (tree->right, block);
6396 /*-----------------------------------------------------------------*/
6397 /* createFunction - This is the key node that calls the iCode for */
6398 /* generating the code for a function. Note code */
6399 /* is generated function by function, later when */
6400 /* add inter-procedural analysis this will change */
6401 /*-----------------------------------------------------------------*/
6403 createFunction (symbol * name, ast * body)
6409 iCode *piCode = NULL;
6411 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6412 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6414 /* if check function return 0 then some problem */
6415 if (checkFunction (name, NULL) == 0)
6418 /* create a dummy block if none exists */
6420 body = newNode (BLOCK, NULL, NULL);
6424 /* check if the function name already in the symbol table */
6425 if ((csym = findSym (SymbolTab, NULL, name->name)))
6428 /* special case for compiler defined functions
6429 we need to add the name to the publics list : this
6430 actually means we are now compiling the compiler
6434 addSet (&publics, name);
6439 addSymChain (&name);
6440 allocVariables (name);
6442 name->lastLine = lexLineno;
6445 /* set the stack pointer */
6446 stackPtr = -port->stack.direction * port->stack.call_overhead;
6449 if (IFFUNC_ISISR (name->type))
6450 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6452 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6454 if (options.useXstack)
6455 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6457 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6460 fetype = getSpec (name->type); /* get the specifier for the function */
6461 /* if this is a reentrant function then */
6462 if (IFFUNC_ISREENT (name->type))
6465 inlineState.count = 0;
6466 expandInlineFuncs (body, NULL);
6468 if (FUNC_ISINLINE (name->type))
6469 name->funcTree = copyAst (body);
6471 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6473 /* do processing for parameters that are passed in registers */
6474 processRegParms (FUNC_ARGS(name->type), body);
6476 /* set the stack pointer */
6480 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6482 /* allocate & autoinit the block variables */
6483 processBlockVars (body, &stack, ALLOCATE);
6485 /* name needs to be mangled */
6486 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6488 body = resolveSymbols (body); /* resolve the symbols */
6489 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6491 /* save the stack information */
6492 if (options.useXstack)
6493 name->xstack = SPEC_STAK (fetype) = stack;
6495 name->stack = SPEC_STAK (fetype) = stack;
6497 ex = newAst_VALUE (symbolVal (name)); /* create name */
6498 ex = newNode (FUNCTION, ex, body);
6499 ex->values.args = FUNC_ARGS(name->type);
6501 if (options.dump_tree)
6506 /* Do not generate code for inline functions unless extern also. */
6508 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6511 /* Temporary hack: always generate code for static inline functions. */
6512 /* Ideally static inline functions should only be generated if needed. */
6513 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6517 /* create the node & generate intermediate code */
6519 codeOutBuf = &code->oBuf;
6520 piCode = iCodeFromAst (ex);
6521 name->generated = 1;
6526 eBBlockFromiCode (piCode);
6528 /* if there are any statics then do them */
6531 GcurMemmap = statsg;
6532 codeOutBuf = &statsg->oBuf;
6533 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6539 /* dealloc the block variables */
6540 processBlockVars (body, &stack, DEALLOCATE);
6541 outputDebugStackSymbols();
6542 /* deallocate paramaters */
6543 deallocParms (FUNC_ARGS(name->type));
6545 if (IFFUNC_ISREENT (name->type))
6548 /* we are done freeup memory & cleanup */
6550 if (port->reset_labelKey)
6553 FUNC_HASBODY(name->type) = 1;
6554 addSet (&operKeyReset, name);
6555 applyToSet (operKeyReset, resetParmKey);
6560 cleanUpLevel (LabelTab, 0);
6561 cleanUpBlock (StructTab, 1);
6562 cleanUpBlock (TypedefTab, 1);
6564 xstack->syms = NULL;
6565 istack->syms = NULL;
6570 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6571 /*-----------------------------------------------------------------*/
6572 /* ast_print : prints the ast (for debugging purposes) */
6573 /*-----------------------------------------------------------------*/
6575 void ast_print (ast * tree, FILE *outfile, int indent)
6580 /* can print only decorated trees */
6581 if (!tree->decorated) return;
6583 /* if any child is an error | this one is an error do nothing */
6584 if (tree->isError ||
6585 (tree->left && tree->left->isError) ||
6586 (tree->right && tree->right->isError)) {
6587 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6591 /* print the line */
6592 /* if not block & function */
6593 if (tree->type == EX_OP &&
6594 (tree->opval.op != FUNCTION &&
6595 tree->opval.op != BLOCK &&
6596 tree->opval.op != NULLOP)) {
6599 if (tree->opval.op == FUNCTION) {
6601 value *args=FUNC_ARGS(tree->left->opval.val->type);
6602 fprintf(outfile,"FUNCTION (%s=%p) type (",
6603 tree->left->opval.val->name, tree);
6604 printTypeChain (tree->left->opval.val->type->next,outfile);
6605 fprintf(outfile,") args (");
6608 fprintf (outfile, ", ");
6610 printTypeChain (args ? args->type : NULL, outfile);
6612 args= args ? args->next : NULL;
6614 fprintf(outfile,")\n");
6615 ast_print(tree->left,outfile,indent);
6616 ast_print(tree->right,outfile,indent);
6619 if (tree->opval.op == BLOCK) {
6620 symbol *decls = tree->values.sym;
6621 INDENT(indent,outfile);
6622 fprintf(outfile,"{\n");
6624 INDENT(indent+2,outfile);
6625 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6626 decls->name, decls);
6627 printTypeChain(decls->type,outfile);
6628 fprintf(outfile,")\n");
6630 decls = decls->next;
6632 ast_print(tree->right,outfile,indent+2);
6633 INDENT(indent,outfile);
6634 fprintf(outfile,"}\n");
6637 if (tree->opval.op == NULLOP) {
6638 ast_print(tree->left,outfile,indent);
6639 ast_print(tree->right,outfile,indent);
6642 INDENT(indent,outfile);
6644 /*------------------------------------------------------------------*/
6645 /*----------------------------*/
6646 /* leaf has been reached */
6647 /*----------------------------*/
6648 /* if this is of type value */
6649 /* just get the type */
6650 if (tree->type == EX_VALUE) {
6652 if (IS_LITERAL (tree->opval.val->etype)) {
6653 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6654 if (SPEC_USIGN (tree->opval.val->etype))
6655 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6657 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6658 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6659 floatFromVal(tree->opval.val));
6660 } else if (tree->opval.val->sym) {
6661 /* if the undefined flag is set then give error message */
6662 if (tree->opval.val->sym->undefined) {
6663 fprintf(outfile,"UNDEFINED SYMBOL ");
6665 fprintf(outfile,"SYMBOL ");
6667 fprintf(outfile,"(%s=%p @ %p)",
6668 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6671 fprintf(outfile," type (");
6672 printTypeChain(tree->ftype,outfile);
6673 fprintf(outfile,")\n");
6675 fprintf(outfile,"\n");
6680 /* if type link for the case of cast */
6681 if (tree->type == EX_LINK) {
6682 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6683 printTypeChain(tree->opval.lnk,outfile);
6684 fprintf(outfile,")\n");
6689 /* depending on type of operator do */
6691 switch (tree->opval.op) {
6692 /*------------------------------------------------------------------*/
6693 /*----------------------------*/
6695 /*----------------------------*/
6697 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6698 printTypeChain(tree->ftype,outfile);
6699 fprintf(outfile,")\n");
6700 ast_print(tree->left,outfile,indent+2);
6701 ast_print(tree->right,outfile,indent+2);
6704 /*------------------------------------------------------------------*/
6705 /*----------------------------*/
6707 /*----------------------------*/
6709 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6710 printTypeChain(tree->ftype,outfile);
6711 fprintf(outfile,")\n");
6712 ast_print(tree->left,outfile,indent+2);
6713 ast_print(tree->right,outfile,indent+2);
6716 /*------------------------------------------------------------------*/
6717 /*----------------------------*/
6718 /* struct/union pointer */
6719 /*----------------------------*/
6721 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6722 printTypeChain(tree->ftype,outfile);
6723 fprintf(outfile,")\n");
6724 ast_print(tree->left,outfile,indent+2);
6725 ast_print(tree->right,outfile,indent+2);
6728 /*------------------------------------------------------------------*/
6729 /*----------------------------*/
6730 /* ++/-- operation */
6731 /*----------------------------*/
6734 fprintf(outfile,"post-");
6736 fprintf(outfile,"pre-");
6737 fprintf(outfile,"INC_OP (%p) type (",tree);
6738 printTypeChain(tree->ftype,outfile);
6739 fprintf(outfile,")\n");
6740 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6741 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6746 fprintf(outfile,"post-");
6748 fprintf(outfile,"pre-");
6749 fprintf(outfile,"DEC_OP (%p) type (",tree);
6750 printTypeChain(tree->ftype,outfile);
6751 fprintf(outfile,")\n");
6752 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6753 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6756 /*------------------------------------------------------------------*/
6757 /*----------------------------*/
6759 /*----------------------------*/
6762 fprintf(outfile,"& (%p) type (",tree);
6763 printTypeChain(tree->ftype,outfile);
6764 fprintf(outfile,")\n");
6765 ast_print(tree->left,outfile,indent+2);
6766 ast_print(tree->right,outfile,indent+2);
6768 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6769 printTypeChain(tree->ftype,outfile);
6770 fprintf(outfile,")\n");
6771 ast_print(tree->left,outfile,indent+2);
6772 ast_print(tree->right,outfile,indent+2);
6775 /*----------------------------*/
6777 /*----------------------------*/
6779 fprintf(outfile,"OR (%p) type (",tree);
6780 printTypeChain(tree->ftype,outfile);
6781 fprintf(outfile,")\n");
6782 ast_print(tree->left,outfile,indent+2);
6783 ast_print(tree->right,outfile,indent+2);
6785 /*------------------------------------------------------------------*/
6786 /*----------------------------*/
6788 /*----------------------------*/
6790 fprintf(outfile,"XOR (%p) type (",tree);
6791 printTypeChain(tree->ftype,outfile);
6792 fprintf(outfile,")\n");
6793 ast_print(tree->left,outfile,indent+2);
6794 ast_print(tree->right,outfile,indent+2);
6797 /*------------------------------------------------------------------*/
6798 /*----------------------------*/
6800 /*----------------------------*/
6802 fprintf(outfile,"DIV (%p) type (",tree);
6803 printTypeChain(tree->ftype,outfile);
6804 fprintf(outfile,")\n");
6805 ast_print(tree->left,outfile,indent+2);
6806 ast_print(tree->right,outfile,indent+2);
6808 /*------------------------------------------------------------------*/
6809 /*----------------------------*/
6811 /*----------------------------*/
6813 fprintf(outfile,"MOD (%p) type (",tree);
6814 printTypeChain(tree->ftype,outfile);
6815 fprintf(outfile,")\n");
6816 ast_print(tree->left,outfile,indent+2);
6817 ast_print(tree->right,outfile,indent+2);
6820 /*------------------------------------------------------------------*/
6821 /*----------------------------*/
6822 /* address dereference */
6823 /*----------------------------*/
6824 case '*': /* can be unary : if right is null then unary operation */
6826 fprintf(outfile,"DEREF (%p) type (",tree);
6827 printTypeChain(tree->ftype,outfile);
6828 fprintf(outfile,")\n");
6829 ast_print(tree->left,outfile,indent+2);
6832 /*------------------------------------------------------------------*/
6833 /*----------------------------*/
6834 /* multiplication */
6835 /*----------------------------*/
6836 fprintf(outfile,"MULT (%p) type (",tree);
6837 printTypeChain(tree->ftype,outfile);
6838 fprintf(outfile,")\n");
6839 ast_print(tree->left,outfile,indent+2);
6840 ast_print(tree->right,outfile,indent+2);
6844 /*------------------------------------------------------------------*/
6845 /*----------------------------*/
6846 /* unary '+' operator */
6847 /*----------------------------*/
6851 fprintf(outfile,"UPLUS (%p) type (",tree);
6852 printTypeChain(tree->ftype,outfile);
6853 fprintf(outfile,")\n");
6854 ast_print(tree->left,outfile,indent+2);
6856 /*------------------------------------------------------------------*/
6857 /*----------------------------*/
6859 /*----------------------------*/
6860 fprintf(outfile,"ADD (%p) type (",tree);
6861 printTypeChain(tree->ftype,outfile);
6862 fprintf(outfile,")\n");
6863 ast_print(tree->left,outfile,indent+2);
6864 ast_print(tree->right,outfile,indent+2);
6867 /*------------------------------------------------------------------*/
6868 /*----------------------------*/
6870 /*----------------------------*/
6871 case '-': /* can be unary */
6873 fprintf(outfile,"UMINUS (%p) type (",tree);
6874 printTypeChain(tree->ftype,outfile);
6875 fprintf(outfile,")\n");
6876 ast_print(tree->left,outfile,indent+2);
6878 /*------------------------------------------------------------------*/
6879 /*----------------------------*/
6881 /*----------------------------*/
6882 fprintf(outfile,"SUB (%p) type (",tree);
6883 printTypeChain(tree->ftype,outfile);
6884 fprintf(outfile,")\n");
6885 ast_print(tree->left,outfile,indent+2);
6886 ast_print(tree->right,outfile,indent+2);
6889 /*------------------------------------------------------------------*/
6890 /*----------------------------*/
6892 /*----------------------------*/
6894 fprintf(outfile,"COMPL (%p) type (",tree);
6895 printTypeChain(tree->ftype,outfile);
6896 fprintf(outfile,")\n");
6897 ast_print(tree->left,outfile,indent+2);
6899 /*------------------------------------------------------------------*/
6900 /*----------------------------*/
6902 /*----------------------------*/
6904 fprintf(outfile,"NOT (%p) type (",tree);
6905 printTypeChain(tree->ftype,outfile);
6906 fprintf(outfile,")\n");
6907 ast_print(tree->left,outfile,indent+2);
6909 /*------------------------------------------------------------------*/
6910 /*----------------------------*/
6912 /*----------------------------*/
6914 fprintf(outfile,"RRC (%p) type (",tree);
6915 printTypeChain(tree->ftype,outfile);
6916 fprintf(outfile,")\n");
6917 ast_print(tree->left,outfile,indent+2);
6921 fprintf(outfile,"RLC (%p) type (",tree);
6922 printTypeChain(tree->ftype,outfile);
6923 fprintf(outfile,")\n");
6924 ast_print(tree->left,outfile,indent+2);
6927 fprintf(outfile,"SWAP (%p) type (",tree);
6928 printTypeChain(tree->ftype,outfile);
6929 fprintf(outfile,")\n");
6930 ast_print(tree->left,outfile,indent+2);
6933 fprintf(outfile,"GETHBIT (%p) type (",tree);
6934 printTypeChain(tree->ftype,outfile);
6935 fprintf(outfile,")\n");
6936 ast_print(tree->left,outfile,indent+2);
6939 fprintf(outfile,"GETABIT (%p) type (",tree);
6940 printTypeChain(tree->ftype,outfile);
6941 fprintf(outfile,")\n");
6942 ast_print(tree->left,outfile,indent+2);
6943 ast_print(tree->right,outfile,indent+2);
6946 fprintf(outfile,"GETBYTE (%p) type (",tree);
6947 printTypeChain(tree->ftype,outfile);
6948 fprintf(outfile,")\n");
6949 ast_print(tree->left,outfile,indent+2);
6950 ast_print(tree->right,outfile,indent+2);
6953 fprintf(outfile,"GETWORD (%p) type (",tree);
6954 printTypeChain(tree->ftype,outfile);
6955 fprintf(outfile,")\n");
6956 ast_print(tree->left,outfile,indent+2);
6957 ast_print(tree->right,outfile,indent+2);
6960 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6961 printTypeChain(tree->ftype,outfile);
6962 fprintf(outfile,")\n");
6963 ast_print(tree->left,outfile,indent+2);
6964 ast_print(tree->right,outfile,indent+2);
6967 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6968 printTypeChain(tree->ftype,outfile);
6969 fprintf(outfile,")\n");
6970 ast_print(tree->left,outfile,indent+2);
6971 ast_print(tree->right,outfile,indent+2);
6973 /*------------------------------------------------------------------*/
6974 /*----------------------------*/
6976 /*----------------------------*/
6977 case CAST: /* change the type */
6978 fprintf(outfile,"CAST (%p) from type (",tree);
6979 printTypeChain(tree->right->ftype,outfile);
6980 fprintf(outfile,") to type (");
6981 printTypeChain(tree->ftype,outfile);
6982 fprintf(outfile,")\n");
6983 ast_print(tree->right,outfile,indent+2);
6987 fprintf(outfile,"ANDAND (%p) type (",tree);
6988 printTypeChain(tree->ftype,outfile);
6989 fprintf(outfile,")\n");
6990 ast_print(tree->left,outfile,indent+2);
6991 ast_print(tree->right,outfile,indent+2);
6994 fprintf(outfile,"OROR (%p) type (",tree);
6995 printTypeChain(tree->ftype,outfile);
6996 fprintf(outfile,")\n");
6997 ast_print(tree->left,outfile,indent+2);
6998 ast_print(tree->right,outfile,indent+2);
7001 /*------------------------------------------------------------------*/
7002 /*----------------------------*/
7003 /* comparison operators */
7004 /*----------------------------*/
7006 fprintf(outfile,"GT(>) (%p) type (",tree);
7007 printTypeChain(tree->ftype,outfile);
7008 fprintf(outfile,")\n");
7009 ast_print(tree->left,outfile,indent+2);
7010 ast_print(tree->right,outfile,indent+2);
7013 fprintf(outfile,"LT(<) (%p) type (",tree);
7014 printTypeChain(tree->ftype,outfile);
7015 fprintf(outfile,")\n");
7016 ast_print(tree->left,outfile,indent+2);
7017 ast_print(tree->right,outfile,indent+2);
7020 fprintf(outfile,"LE(<=) (%p) type (",tree);
7021 printTypeChain(tree->ftype,outfile);
7022 fprintf(outfile,")\n");
7023 ast_print(tree->left,outfile,indent+2);
7024 ast_print(tree->right,outfile,indent+2);
7027 fprintf(outfile,"GE(>=) (%p) type (",tree);
7028 printTypeChain(tree->ftype,outfile);
7029 fprintf(outfile,")\n");
7030 ast_print(tree->left,outfile,indent+2);
7031 ast_print(tree->right,outfile,indent+2);
7034 fprintf(outfile,"EQ(==) (%p) type (",tree);
7035 printTypeChain(tree->ftype,outfile);
7036 fprintf(outfile,")\n");
7037 ast_print(tree->left,outfile,indent+2);
7038 ast_print(tree->right,outfile,indent+2);
7041 fprintf(outfile,"NE(!=) (%p) type (",tree);
7042 printTypeChain(tree->ftype,outfile);
7043 fprintf(outfile,")\n");
7044 ast_print(tree->left,outfile,indent+2);
7045 ast_print(tree->right,outfile,indent+2);
7046 /*------------------------------------------------------------------*/
7047 /*----------------------------*/
7049 /*----------------------------*/
7050 case SIZEOF: /* evaluate wihout code generation */
7051 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7054 /*------------------------------------------------------------------*/
7055 /*----------------------------*/
7056 /* conditional operator '?' */
7057 /*----------------------------*/
7059 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7060 printTypeChain(tree->ftype,outfile);
7061 fprintf(outfile,")\n");
7062 ast_print(tree->left,outfile,indent+2);
7063 ast_print(tree->right,outfile,indent+2);
7067 fprintf(outfile,"COLON(:) (%p) type (",tree);
7068 printTypeChain(tree->ftype,outfile);
7069 fprintf(outfile,")\n");
7070 ast_print(tree->left,outfile,indent+2);
7071 ast_print(tree->right,outfile,indent+2);
7074 /*------------------------------------------------------------------*/
7075 /*----------------------------*/
7076 /* assignment operators */
7077 /*----------------------------*/
7079 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7080 printTypeChain(tree->ftype,outfile);
7081 fprintf(outfile,")\n");
7082 ast_print(tree->left,outfile,indent+2);
7083 ast_print(tree->right,outfile,indent+2);
7086 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7087 printTypeChain(tree->ftype,outfile);
7088 fprintf(outfile,")\n");
7089 ast_print(tree->left,outfile,indent+2);
7090 ast_print(tree->right,outfile,indent+2);
7093 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7094 printTypeChain(tree->ftype,outfile);
7095 fprintf(outfile,")\n");
7096 ast_print(tree->left,outfile,indent+2);
7097 ast_print(tree->right,outfile,indent+2);
7100 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7101 printTypeChain(tree->ftype,outfile);
7102 fprintf(outfile,")\n");
7103 ast_print(tree->left,outfile,indent+2);
7104 ast_print(tree->right,outfile,indent+2);
7107 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7108 printTypeChain(tree->ftype,outfile);
7109 fprintf(outfile,")\n");
7110 ast_print(tree->left,outfile,indent+2);
7111 ast_print(tree->right,outfile,indent+2);
7114 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7115 printTypeChain(tree->ftype,outfile);
7116 fprintf(outfile,")\n");
7117 ast_print(tree->left,outfile,indent+2);
7118 ast_print(tree->right,outfile,indent+2);
7121 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7122 printTypeChain(tree->ftype,outfile);
7123 fprintf(outfile,")\n");
7124 ast_print(tree->left,outfile,indent+2);
7125 ast_print(tree->right,outfile,indent+2);
7127 /*------------------------------------------------------------------*/
7128 /*----------------------------*/
7130 /*----------------------------*/
7132 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7133 printTypeChain(tree->ftype,outfile);
7134 fprintf(outfile,")\n");
7135 ast_print(tree->left,outfile,indent+2);
7136 ast_print(tree->right,outfile,indent+2);
7138 /*------------------------------------------------------------------*/
7139 /*----------------------------*/
7141 /*----------------------------*/
7143 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7144 printTypeChain(tree->ftype,outfile);
7145 fprintf(outfile,")\n");
7146 ast_print(tree->left,outfile,indent+2);
7147 ast_print(tree->right,outfile,indent+2);
7149 /*------------------------------------------------------------------*/
7150 /*----------------------------*/
7151 /* straight assignemnt */
7152 /*----------------------------*/
7154 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7155 printTypeChain(tree->ftype,outfile);
7156 fprintf(outfile,")\n");
7157 ast_print(tree->left,outfile,indent+2);
7158 ast_print(tree->right,outfile,indent+2);
7160 /*------------------------------------------------------------------*/
7161 /*----------------------------*/
7162 /* comma operator */
7163 /*----------------------------*/
7165 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7166 printTypeChain(tree->ftype,outfile);
7167 fprintf(outfile,")\n");
7168 ast_print(tree->left,outfile,indent+2);
7169 ast_print(tree->right,outfile,indent+2);
7171 /*------------------------------------------------------------------*/
7172 /*----------------------------*/
7174 /*----------------------------*/
7177 fprintf(outfile,"CALL (%p) type (",tree);
7178 printTypeChain(tree->ftype,outfile);
7179 fprintf(outfile,")\n");
7180 ast_print(tree->left,outfile,indent+2);
7181 ast_print(tree->right,outfile,indent+2);
7184 fprintf(outfile,"PARMS\n");
7185 ast_print(tree->left,outfile,indent+2);
7186 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7187 ast_print(tree->right,outfile,indent+2);
7190 /*------------------------------------------------------------------*/
7191 /*----------------------------*/
7192 /* return statement */
7193 /*----------------------------*/
7195 fprintf(outfile,"RETURN (%p) type (",tree);
7197 printTypeChain(tree->right->ftype,outfile);
7199 fprintf(outfile,")\n");
7200 ast_print(tree->right,outfile,indent+2);
7202 /*------------------------------------------------------------------*/
7203 /*----------------------------*/
7204 /* label statement */
7205 /*----------------------------*/
7207 fprintf(outfile,"LABEL (%p)\n",tree);
7208 ast_print(tree->left,outfile,indent+2);
7209 ast_print(tree->right,outfile,indent);
7211 /*------------------------------------------------------------------*/
7212 /*----------------------------*/
7213 /* switch statement */
7214 /*----------------------------*/
7218 fprintf(outfile,"SWITCH (%p) ",tree);
7219 ast_print(tree->left,outfile,0);
7220 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7221 INDENT(indent+2,outfile);
7222 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7223 (int) ulFromVal(val),
7224 tree->values.switchVals.swNum,
7225 (int) ulFromVal(val));
7227 ast_print(tree->right,outfile,indent);
7230 /*------------------------------------------------------------------*/
7231 /*----------------------------*/
7233 /*----------------------------*/
7235 fprintf(outfile,"IF (%p) \n",tree);
7236 ast_print(tree->left,outfile,indent+2);
7237 if (tree->trueLabel) {
7238 INDENT(indent+2,outfile);
7239 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7241 if (tree->falseLabel) {
7242 INDENT(indent+2,outfile);
7243 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7245 ast_print(tree->right,outfile,indent+2);
7247 /*----------------------------*/
7248 /* goto Statement */
7249 /*----------------------------*/
7251 fprintf(outfile,"GOTO (%p) \n",tree);
7252 ast_print(tree->left,outfile,indent+2);
7253 fprintf(outfile,"\n");
7255 /*------------------------------------------------------------------*/
7256 /*----------------------------*/
7258 /*----------------------------*/
7260 fprintf(outfile,"FOR (%p) \n",tree);
7261 if (AST_FOR( tree, initExpr)) {
7262 INDENT(indent+2,outfile);
7263 fprintf(outfile,"INIT EXPR ");
7264 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7266 if (AST_FOR( tree, condExpr)) {
7267 INDENT(indent+2,outfile);
7268 fprintf(outfile,"COND EXPR ");
7269 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7271 if (AST_FOR( tree, loopExpr)) {
7272 INDENT(indent+2,outfile);
7273 fprintf(outfile,"LOOP EXPR ");
7274 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7276 fprintf(outfile,"FOR LOOP BODY \n");
7277 ast_print(tree->left,outfile,indent+2);
7280 fprintf(outfile,"CRITICAL (%p) \n",tree);
7281 ast_print(tree->left,outfile,indent+2);
7289 ast_print(t,stdout,0);
7292 /*-----------------------------------------------------------------*/
7293 /* astErrors : returns non-zero if errors present in tree */
7294 /*-----------------------------------------------------------------*/
7295 int astErrors(ast *t)
7304 if (t->type == EX_VALUE
7305 && t->opval.val->sym
7306 && t->opval.val->sym->undefined)
7309 errors += astErrors(t->left);
7310 errors += astErrors(t->right);