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 if (ilist && ilist->type != INIT_DEEP)
984 werror (E_INIT_STRUCT, "");
988 iloop = ilist ? ilist->init.deep : NULL;
990 for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
992 /* if we have come to end */
993 if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
996 if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
999 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
1000 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
1001 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast, rootValue)), RESULT_TYPE_NONE);
1002 iloop = iloop ? iloop->next : NULL;
1008 if (IS_AST_VALUE (sym))
1009 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1010 W_EXCESS_INITIALIZERS, "struct",
1011 sym->opval.val->sym->name);
1013 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1019 /*-----------------------------------------------------------------*/
1020 /* createIvalArray - generates code for array initialization */
1021 /*-----------------------------------------------------------------*/
1023 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1027 int lcnt = 0, size = 0;
1028 literalList *literalL;
1029 sym_link * etype = getSpec (type);
1031 /* take care of the special case */
1032 /* array of characters can be init */
1034 if (IS_CHAR (type->next))
1035 if ((rast = createIvalCharPtr (sym,
1037 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1040 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1042 /* not the special case */
1043 if (ilist && ilist->type != INIT_DEEP)
1045 werror (E_INIT_STRUCT, "");
1049 iloop = ilist ? ilist->init.deep : NULL;
1050 lcnt = DCL_ELEM (type);
1053 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1058 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
1062 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1064 rast = newNode(ARRAYINIT, aSym, NULL);
1065 rast->values.constlist = literalL;
1067 // Make sure size is set to length of initializer list.
1071 iloop = iloop->next;
1074 if (lcnt && size > lcnt)
1076 // Array size was specified, and we have more initializers than needed.
1077 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1078 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1088 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1093 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1094 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1095 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1097 iloop = (iloop ? iloop->next : NULL);
1099 /* no of elements given and we */
1100 /* have generated for all of them */
1103 // is this a better way? at least it won't crash
1104 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1105 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1112 /* if we have not been given a size */
1113 if (!DCL_ELEM (type))
1115 /* check, if it's a flexible array */
1116 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1117 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1119 DCL_ELEM (type) = size;
1122 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1126 /*-----------------------------------------------------------------*/
1127 /* createIvalCharPtr - generates initial values for char pointers */
1128 /*-----------------------------------------------------------------*/
1130 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1135 /* if this is a pointer & right is a literal array then */
1136 /* just assignment will do */
1137 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1138 SPEC_SCLS (iexpr->etype) == S_CODE)
1139 && IS_ARRAY (iexpr->ftype)))
1140 return newNode ('=', sym, iexpr);
1142 /* left side is an array so we have to assign each element */
1145 /* for each character generate an assignment */
1146 /* to the array element */
1148 unsigned int symsize = getSize (type);
1150 if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
1153 for (i = 0; i < symsize; ++i)
1155 rast = newNode (NULLOP,
1159 newAst_VALUE (valueFromLit ((float) i))),
1160 newAst_VALUE (valueFromLit (0))));
1163 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1166 if ((IS_LITERAL (iexpr->etype) ||
1167 SPEC_SCLS (iexpr->etype) == S_CODE)
1168 && IS_ARRAY (iexpr->ftype))
1170 /* for each character generate an assignment */
1171 /* to the array element */
1172 char *s = SPEC_CVAL (iexpr->etype).v_char;
1174 unsigned int symsize = getSize (type);
1176 size = getSize (iexpr->ftype);
1177 if (symsize && size > symsize)
1181 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1183 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1189 for (i = 0; i < size; i++)
1191 rast = newNode (NULLOP,
1195 newAst_VALUE (valueFromLit ((float) i))),
1196 newAst_VALUE (valueFromLit (*s++))));
1199 // now WE don't need iexpr's symbol anymore
1200 freeStringSymbol(AST_SYMBOL(iexpr));
1202 /* if we have not been given a size */
1203 if (!DCL_ELEM (type))
1205 /* check, if it's a flexible array */
1206 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1207 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1209 DCL_ELEM (type) = size;
1212 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1218 /*-----------------------------------------------------------------*/
1219 /* createIvalPtr - generates initial value for pointers */
1220 /*-----------------------------------------------------------------*/
1222 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1228 if (ilist && ilist->type == INIT_DEEP)
1229 ilist = ilist->init.deep;
1231 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1233 /* if character pointer */
1234 if (IS_CHAR (type->next))
1235 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1238 return newNode ('=', sym, iexpr);
1241 /*-----------------------------------------------------------------*/
1242 /* createIval - generates code for initial value */
1243 /*-----------------------------------------------------------------*/
1245 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1249 if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
1252 /* if structure then */
1253 if (IS_STRUCT (type))
1254 rast = createIvalStruct (sym, type, ilist, rootValue);
1256 /* if this is a pointer */
1258 rast = createIvalPtr (sym, type, ilist, rootValue);
1260 /* if this is an array */
1261 if (IS_ARRAY (type))
1262 rast = createIvalArray (sym, type, ilist, rootValue);
1264 /* if type is SPECIFIER */
1266 rast = createIvalType (sym, type, ilist);
1269 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1271 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1274 /*-----------------------------------------------------------------*/
1275 /* initAggregates - initialises aggregate variables with initv */
1276 /*-----------------------------------------------------------------*/
1277 ast * initAggregates (symbol * sym, initList * ival, ast * wid)
1279 ast *newAst = newAst_VALUE (symbolVal (sym));
1280 return createIval (newAst, sym->type, ival, wid, newAst);
1283 /*-----------------------------------------------------------------*/
1284 /* gatherAutoInit - creates assignment expressions for initial */
1286 /*-----------------------------------------------------------------*/
1288 gatherAutoInit (symbol * autoChain)
1295 for (sym = autoChain; sym; sym = sym->next)
1297 /* resolve the symbols in the ival */
1299 resolveIvalSym (sym->ival, sym->type);
1302 /* if we are PIC16 port,
1303 * and this is a static,
1304 * and have initial value,
1305 * and not S_CODE, don't emit in gs segment,
1306 * but allow glue.c:pic16emitRegularMap to put symbol
1307 * in idata section */
1308 if(TARGET_IS_PIC16 &&
1309 IS_STATIC (sym->etype) && sym->ival
1310 && SPEC_SCLS(sym->etype) != S_CODE) {
1311 SPEC_SCLS (sym->etype) = S_DATA;
1316 /* if this is a static variable & has an */
1317 /* initial value the code needs to be lifted */
1318 /* here to the main portion since they can be */
1319 /* initialised only once at the start */
1320 if (IS_STATIC (sym->etype) && sym->ival &&
1321 SPEC_SCLS (sym->etype) != S_CODE)
1325 /* insert the symbol into the symbol table */
1326 /* with level = 0 & name = rname */
1327 newSym = copySymbol (sym);
1328 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1330 /* now lift the code to main */
1331 if (IS_AGGREGATE (sym->type)) {
1332 work = initAggregates (sym, sym->ival, NULL);
1334 if (getNelements(sym->type, sym->ival)>1) {
1335 werrorfl (sym->fileDef, sym->lineDef,
1336 W_EXCESS_INITIALIZERS, "scalar",
1339 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1340 list2expr (sym->ival));
1343 setAstFileLine (work, sym->fileDef, sym->lineDef);
1347 staticAutos = newNode (NULLOP, staticAutos, work);
1354 /* if there is an initial value */
1355 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1357 initList *ilist = sym->ival;
1359 while (ilist->type == INIT_DEEP)
1361 ilist = ilist->init.deep;
1364 /* update lineno for error msg */
1365 filename = sym->fileDef;
1366 lineno = sym->lineDef;
1367 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1369 if (IS_AGGREGATE (sym->type))
1371 work = initAggregates (sym, sym->ival, NULL);
1375 if (getNelements(sym->type, sym->ival)>1)
1377 werrorfl (sym->fileDef, sym->lineDef,
1378 W_EXCESS_INITIALIZERS, "scalar",
1381 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1382 list2expr (sym->ival));
1386 setAstFileLine (work, sym->fileDef, sym->lineDef);
1390 init = newNode (NULLOP, init, work);
1399 /*-----------------------------------------------------------------*/
1400 /* freeStringSymbol - delete a literal string if no more usage */
1401 /*-----------------------------------------------------------------*/
1402 void freeStringSymbol(symbol *sym) {
1403 /* make sure this is a literal string */
1404 assert (sym->isstrlit);
1405 if (--sym->isstrlit == 0) { // lower the usage count
1406 memmap *segment=SPEC_OCLS(sym->etype);
1408 deleteSetItem(&segment->syms, sym);
1413 /*-----------------------------------------------------------------*/
1414 /* stringToSymbol - creates a symbol from a literal string */
1415 /*-----------------------------------------------------------------*/
1417 stringToSymbol (value * val)
1419 char name[SDCC_NAME_MAX + 1];
1420 static int charLbl = 0;
1425 // have we heard this before?
1426 for (sp = statsg->syms; sp; sp = sp->next)
1429 size = getSize (sym->type);
1430 if (sym->isstrlit && size == getSize (val->type) &&
1431 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1433 // yes, this is old news. Don't publish it again.
1434 sym->isstrlit++; // but raise the usage count
1435 return symbolVal (sym);
1439 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1440 sym = newSymbol (name, 0); /* make it @ level 0 */
1441 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1443 /* copy the type from the value passed */
1444 sym->type = copyLinkChain (val->type);
1445 sym->etype = getSpec (sym->type);
1446 /* change to storage class & output class */
1447 SPEC_SCLS (sym->etype) = S_CODE;
1448 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1449 SPEC_STAT (sym->etype) = 1;
1450 /* make the level & block = 0 */
1451 sym->block = sym->level = 0;
1453 /* create an ival */
1454 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1459 allocVariables (sym);
1462 return symbolVal (sym);
1466 /*-----------------------------------------------------------------*/
1467 /* processBlockVars - will go thru the ast looking for block if */
1468 /* a block is found then will allocate the syms */
1469 /* will also gather the auto inits present */
1470 /*-----------------------------------------------------------------*/
1472 processBlockVars (ast * tree, int *stack, int action)
1477 /* if this is a block */
1478 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1482 if (action == ALLOCATE)
1484 *stack += allocVariables (tree->values.sym);
1485 autoInit = gatherAutoInit (tree->values.sym);
1487 /* if there are auto inits then do them */
1489 tree->left = newNode (NULLOP, autoInit, tree->left);
1491 else /* action is deallocate */
1492 deallocLocal (tree->values.sym);
1495 processBlockVars (tree->left, stack, action);
1496 processBlockVars (tree->right, stack, action);
1500 /*-------------------------------------------------------------*/
1501 /* constExprTree - returns TRUE if this tree is a constant */
1503 /*-------------------------------------------------------------*/
1504 bool constExprTree (ast *cexpr) {
1510 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1512 switch (cexpr->type)
1515 if (IS_AST_LIT_VALUE(cexpr)) {
1516 // this is a literal
1519 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1520 // a function's address will never change
1523 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1524 // an array's address will never change
1527 if (IS_AST_SYM_VALUE(cexpr) &&
1528 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1529 // a symbol in code space will never change
1530 // This is only for the 'char *s="hallo"' case and will have to leave
1531 //printf(" code space symbol");
1536 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1537 "unexpected link in expression tree\n");
1540 if (cexpr->opval.op==ARRAYINIT) {
1541 // this is a list of literals
1544 if (cexpr->opval.op=='=') {
1545 return constExprTree(cexpr->right);
1547 if (cexpr->opval.op==CAST) {
1548 // cast ignored, maybe we should throw a warning here?
1549 return constExprTree(cexpr->right);
1551 if (cexpr->opval.op=='&') {
1554 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1557 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1562 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1567 /*-----------------------------------------------------------------*/
1568 /* constExprValue - returns the value of a constant expression */
1569 /* or NULL if it is not a constant expression */
1570 /*-----------------------------------------------------------------*/
1572 constExprValue (ast * cexpr, int check)
1574 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1576 /* if this is not a constant then */
1577 if (!IS_LITERAL (cexpr->ftype))
1579 /* then check if this is a literal array
1581 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1582 SPEC_CVAL (cexpr->etype).v_char &&
1583 IS_ARRAY (cexpr->ftype))
1585 value *val = valFromType (cexpr->ftype);
1586 SPEC_SCLS (val->etype) = S_LITERAL;
1587 val->sym = cexpr->opval.val->sym;
1588 val->sym->type = copyLinkChain (cexpr->ftype);
1589 val->sym->etype = getSpec (val->sym->type);
1590 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1594 /* if we are casting a literal value then */
1595 if (IS_AST_OP (cexpr) &&
1596 cexpr->opval.op == CAST &&
1597 IS_LITERAL (cexpr->right->ftype))
1599 return valCastLiteral (cexpr->ftype,
1600 floatFromVal (cexpr->right->opval.val));
1603 if (IS_AST_VALUE (cexpr))
1605 return cexpr->opval.val;
1609 werror (E_CONST_EXPECTED, "found expression");
1614 /* return the value */
1615 if (IS_AST_VALUE (cexpr))
1617 return cexpr->opval.val;
1622 /*-----------------------------------------------------------------*/
1623 /* isLabelInAst - will return true if a given label is found */
1624 /*-----------------------------------------------------------------*/
1626 isLabelInAst (symbol * label, ast * tree)
1628 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1631 if (IS_AST_OP (tree) &&
1632 tree->opval.op == LABEL &&
1633 isSymbolEqual (AST_SYMBOL (tree->left), label))
1636 return isLabelInAst (label, tree->right) &&
1637 isLabelInAst (label, tree->left);
1640 /*-----------------------------------------------------------------*/
1641 /* isLoopCountable - return true if the loop count can be determi- */
1642 /* -ned at compile time . */
1643 /*-----------------------------------------------------------------*/
1645 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1646 symbol ** sym, ast ** init, ast ** end)
1649 /* the loop is considered countable if the following
1650 conditions are true :-
1652 a) initExpr :- <sym> = <const>
1653 b) condExpr :- <sym> < <const1>
1654 c) loopExpr :- <sym> ++
1657 /* first check the initExpr */
1658 if (IS_AST_OP (initExpr) &&
1659 initExpr->opval.op == '=' && /* is assignment */
1660 IS_AST_SYM_VALUE (initExpr->left))
1661 { /* left is a symbol */
1663 *sym = AST_SYMBOL (initExpr->left);
1664 *init = initExpr->right;
1669 /* don't reverse loop with volatile counter */
1670 if (IS_VOLATILE ((*sym)->type))
1673 /* for now the symbol has to be of
1675 if (!IS_INTEGRAL ((*sym)->type))
1678 /* now check condExpr */
1679 if (IS_AST_OP (condExpr))
1682 switch (condExpr->opval.op)
1685 if (IS_AST_SYM_VALUE (condExpr->left) &&
1686 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1687 IS_AST_LIT_VALUE (condExpr->right))
1689 *end = condExpr->right;
1695 if (IS_AST_OP (condExpr->left) &&
1696 condExpr->left->opval.op == '>' &&
1697 IS_AST_LIT_VALUE (condExpr->left->right) &&
1698 IS_AST_SYM_VALUE (condExpr->left->left) &&
1699 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1702 *end = newNode ('+', condExpr->left->right,
1703 newAst_VALUE (constCharVal (1)));
1716 /* check loop expression is of the form <sym>++ */
1717 if (!IS_AST_OP (loopExpr))
1720 /* check if <sym> ++ */
1721 if (loopExpr->opval.op == INC_OP)
1727 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1728 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1735 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1736 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1744 if (loopExpr->opval.op == ADD_ASSIGN)
1747 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1748 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1749 IS_AST_LIT_VALUE (loopExpr->right) &&
1750 AST_ULONG_VALUE (loopExpr->right) != 1)
1758 /*-----------------------------------------------------------------*/
1759 /* astHasVolatile - returns true if ast contains any volatile */
1760 /*-----------------------------------------------------------------*/
1762 astHasVolatile (ast * tree)
1767 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1770 if (IS_AST_OP (tree))
1771 return astHasVolatile (tree->left) ||
1772 astHasVolatile (tree->right);
1777 /*-----------------------------------------------------------------*/
1778 /* astHasPointer - return true if the ast contains any ptr variable */
1779 /*-----------------------------------------------------------------*/
1781 astHasPointer (ast * tree)
1786 if (IS_AST_LINK (tree))
1789 /* if we hit an array expression then check
1790 only the left side */
1791 if (IS_AST_OP (tree) && tree->opval.op == '[')
1792 return astHasPointer (tree->left);
1794 if (IS_AST_VALUE (tree))
1795 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1797 return astHasPointer (tree->left) ||
1798 astHasPointer (tree->right);
1802 /*-----------------------------------------------------------------*/
1803 /* astHasSymbol - return true if the ast has the given symbol */
1804 /*-----------------------------------------------------------------*/
1806 astHasSymbol (ast * tree, symbol * sym)
1808 if (!tree || IS_AST_LINK (tree))
1811 if (IS_AST_VALUE (tree))
1813 if (IS_AST_SYM_VALUE (tree))
1814 return isSymbolEqual (AST_SYMBOL (tree), sym);
1819 return astHasSymbol (tree->left, sym) ||
1820 astHasSymbol (tree->right, sym);
1823 /*-----------------------------------------------------------------*/
1824 /* astHasDeref - return true if the ast has an indirect access */
1825 /*-----------------------------------------------------------------*/
1827 astHasDeref (ast * tree)
1829 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1832 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1834 return astHasDeref (tree->left) || astHasDeref (tree->right);
1837 /*-----------------------------------------------------------------*/
1838 /* isConformingBody - the loop body has to conform to a set of */
1839 /* rules for the loop to be considered reversible read on for rules*/
1840 /*-----------------------------------------------------------------*/
1842 isConformingBody (ast * pbody, symbol * sym, ast * body)
1845 /* we are going to do a pre-order traversal of the
1846 tree && check for the following conditions. (essentially
1847 a set of very shallow tests )
1848 a) the sym passed does not participate in any arithmetic operation
1849 b) There are no function calls
1850 c) all jumps are within the body
1851 d) address of loop control variable not taken
1852 e) if an assignment has a pointer on the left hand side make sure
1853 right does not have loop control variable
1856 /* if we reach the end or a leaf then true */
1857 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1860 /* if anything else is "volatile" */
1861 if (IS_VOLATILE (TETYPE (pbody)))
1864 /* we will walk the body in a pre-order traversal for
1866 switch (pbody->opval.op)
1868 /*------------------------------------------------------------------*/
1870 // if the loopvar is used as an index
1871 /* array op is commutative -- must check both left & right */
1872 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1875 return isConformingBody (pbody->right, sym, body)
1876 && isConformingBody (pbody->left, sym, body);
1878 /*------------------------------------------------------------------*/
1883 /*------------------------------------------------------------------*/
1887 /* sure we are not sym is not modified */
1889 IS_AST_SYM_VALUE (pbody->left) &&
1890 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1894 IS_AST_SYM_VALUE (pbody->right) &&
1895 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1900 /*------------------------------------------------------------------*/
1902 case '*': /* can be unary : if right is null then unary operation */
1907 /* if right is NULL then unary operation */
1908 /*------------------------------------------------------------------*/
1909 /*----------------------------*/
1911 /*----------------------------*/
1914 if (IS_AST_SYM_VALUE (pbody->left) &&
1915 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1918 return isConformingBody (pbody->left, sym, body);
1922 if (astHasSymbol (pbody->left, sym) ||
1923 astHasSymbol (pbody->right, sym))
1928 /*------------------------------------------------------------------*/
1939 if (IS_AST_SYM_VALUE (pbody->left) &&
1940 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1943 if (IS_AST_SYM_VALUE (pbody->right) &&
1944 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1947 return isConformingBody (pbody->left, sym, body) &&
1948 isConformingBody (pbody->right, sym, body);
1956 if (IS_AST_SYM_VALUE (pbody->left) &&
1957 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1959 return isConformingBody (pbody->left, sym, body);
1961 /*------------------------------------------------------------------*/
1973 case SIZEOF: /* evaluate wihout code generation */
1975 if (IS_AST_SYM_VALUE (pbody->left) &&
1976 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1979 if (IS_AST_SYM_VALUE (pbody->right) &&
1980 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1983 return isConformingBody (pbody->left, sym, body) &&
1984 isConformingBody (pbody->right, sym, body);
1986 /*------------------------------------------------------------------*/
1989 /* if left has a pointer & right has loop
1990 control variable then we cannot */
1991 if (astHasPointer (pbody->left) &&
1992 astHasSymbol (pbody->right, sym))
1994 if (astHasVolatile (pbody->left))
1997 if (IS_AST_SYM_VALUE (pbody->left)) {
1998 // if the loopvar has an assignment
1999 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
2001 // if the loopvar is used in another (maybe conditional) block
2002 if (astHasSymbol (pbody->right, sym) &&
2003 (pbody->level >= body->level)) {
2008 if (astHasVolatile (pbody->left))
2011 if (astHasDeref(pbody->right))
2014 return isConformingBody (pbody->left, sym, body) &&
2015 isConformingBody (pbody->right, sym, body);
2026 assert ("Parser should not have generated this\n");
2028 /*------------------------------------------------------------------*/
2029 /*----------------------------*/
2030 /* comma operator */
2031 /*----------------------------*/
2033 return isConformingBody (pbody->left, sym, body) &&
2034 isConformingBody (pbody->right, sym, body);
2036 /*------------------------------------------------------------------*/
2037 /*----------------------------*/
2039 /*----------------------------*/
2041 /* if local & not passed as parameter &
2042 not used to find the function then ok */
2043 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2044 !astHasSymbol (pbody->left, sym))
2050 /*------------------------------------------------------------------*/
2051 /*----------------------------*/
2052 /* return statement */
2053 /*----------------------------*/
2058 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2063 if (astHasSymbol (pbody->left, sym))
2070 return isConformingBody (pbody->left, sym, body) &&
2071 isConformingBody (pbody->right, sym, body);
2074 /*-----------------------------------------------------------------*/
2075 /* isLoopReversible - takes a for loop as input && returns true */
2076 /* if the for loop is reversible. If yes will set the value of */
2077 /* the loop control var & init value & termination value */
2078 /*-----------------------------------------------------------------*/
2080 isLoopReversible (ast * loop, symbol ** loopCntrl,
2081 ast ** init, ast ** end)
2083 /* if option says don't do it then don't */
2084 if (optimize.noLoopReverse)
2086 /* there are several tests to determine this */
2088 /* for loop has to be of the form
2089 for ( <sym> = <const1> ;
2090 [<sym> < <const2>] ;
2091 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2093 if (!isLoopCountable (AST_FOR (loop, initExpr),
2094 AST_FOR (loop, condExpr),
2095 AST_FOR (loop, loopExpr),
2096 loopCntrl, init, end))
2099 /* now do some serious checking on the body of the loop
2102 return isConformingBody (loop->left, *loopCntrl, loop->left);
2106 /*-----------------------------------------------------------------*/
2107 /* replLoopSym - replace the loop sym by loop sym -1 */
2108 /*-----------------------------------------------------------------*/
2110 replLoopSym (ast * body, symbol * sym)
2113 if (!body || IS_AST_LINK (body))
2116 if (IS_AST_SYM_VALUE (body))
2119 if (isSymbolEqual (AST_SYMBOL (body), sym))
2123 body->opval.op = '-';
2124 body->left = newAst_VALUE (symbolVal (sym));
2125 body->right = newAst_VALUE (constCharVal (1));
2133 replLoopSym (body->left, sym);
2134 replLoopSym (body->right, sym);
2138 /*-----------------------------------------------------------------*/
2139 /* reverseLoop - do the actual loop reversal */
2140 /*-----------------------------------------------------------------*/
2142 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2146 /* create the following tree
2151 if (sym) goto for_continue ;
2154 /* put it together piece by piece */
2155 rloop = newNode (NULLOP,
2156 createIf (newAst_VALUE (symbolVal (sym)),
2158 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2161 newAst_VALUE (symbolVal (sym)),
2164 replLoopSym (loop->left, sym);
2165 setAstFileLine (rloop, init->filename, init->lineno);
2167 rloop = newNode (NULLOP,
2169 newAst_VALUE (symbolVal (sym)),
2170 newNode ('-', end, init)),
2171 createLabel (AST_FOR (loop, continueLabel),
2175 newNode (SUB_ASSIGN,
2176 newAst_VALUE (symbolVal (sym)),
2177 newAst_VALUE (constCharVal (1))),
2180 rloop->lineno=init->lineno;
2181 return decorateType (rloop, RESULT_TYPE_NONE);
2185 /*-----------------------------------------------------------------*/
2186 /* searchLitOp - search tree (*ops only) for an ast with literal */
2187 /*-----------------------------------------------------------------*/
2189 searchLitOp (ast *tree, ast **parent, const char *ops)
2193 if (tree && optimize.global_cse)
2195 /* is there a literal operand? */
2197 IS_AST_OP(tree->right) &&
2198 tree->right->right &&
2199 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2201 if (IS_LITERAL (RTYPE (tree->right)) !=
2202 IS_LITERAL (LTYPE (tree->right)))
2204 tree->right->decorated = 0;
2205 tree->decorated = 0;
2209 ret = searchLitOp (tree->right, parent, ops);
2214 IS_AST_OP(tree->left) &&
2215 tree->left->right &&
2216 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2218 if (IS_LITERAL (RTYPE (tree->left)) !=
2219 IS_LITERAL (LTYPE (tree->left)))
2221 tree->left->decorated = 0;
2222 tree->decorated = 0;
2226 ret = searchLitOp (tree->left, parent, ops);
2234 /*-----------------------------------------------------------------*/
2235 /* getResultFromType */
2236 /*-----------------------------------------------------------------*/
2238 getResultTypeFromType (sym_link *type)
2240 /* type = getSpec (type); */
2242 return RESULT_TYPE_BIT;
2243 if (IS_BITFIELD (type))
2245 int blen = SPEC_BLEN (type);
2248 return RESULT_TYPE_BIT;
2250 return RESULT_TYPE_CHAR;
2251 return RESULT_TYPE_INT;
2254 return RESULT_TYPE_CHAR;
2255 if (IS_INT (type) && !IS_LONG (type))
2256 return RESULT_TYPE_INT;
2257 return RESULT_TYPE_OTHER;
2260 /*-----------------------------------------------------------------*/
2261 /* addCast - adds casts to a type specified by RESULT_TYPE */
2262 /*-----------------------------------------------------------------*/
2264 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2267 bool upCasted = FALSE;
2271 case RESULT_TYPE_NONE:
2272 /* if thing smaller than int must be promoted to int */
2274 getSize (tree->etype) >= INTSIZE)
2275 /* promotion not necessary or already an int */
2277 /* char and bits: promote to int */
2278 newLink = newIntLink();
2281 case RESULT_TYPE_BIT:
2283 /* already an int */
2284 bitsForType (tree->etype) >= 16 ||
2285 /* bit to bit operation: don't promote, the code generators
2286 hopefully know everything about promotion rules */
2287 bitsForType (tree->etype) == 1)
2289 newLink = newIntLink();
2292 case RESULT_TYPE_CHAR:
2293 if (IS_CHAR (tree->etype) ||
2294 IS_FLOAT(tree->etype) ||
2295 IS_FIXED(tree->etype))
2297 newLink = newCharLink();
2299 case RESULT_TYPE_INT:
2301 if (getSize (tree->etype) > INTSIZE)
2303 /* warn ("Loosing significant digits"); */
2307 /* char: promote to int */
2309 getSize (tree->etype) >= INTSIZE)
2311 newLink = newIntLink();
2314 case RESULT_TYPE_IFX:
2315 case RESULT_TYPE_OTHER:
2317 /* return type is ifx, long, float: promote char to int */
2318 getSize (tree->etype) >= INTSIZE)
2320 newLink = newIntLink();
2326 tree->decorated = 0;
2327 tree = newNode (CAST, newAst_LINK (newLink), tree);
2328 tree->filename = tree->right->filename;
2329 tree->lineno = tree->right->lineno;
2330 /* keep unsigned type during cast to smaller type,
2331 but not when promoting from char to int */
2333 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2334 return decorateType (tree, resultType);
2337 /*-----------------------------------------------------------------*/
2338 /* resultTypePropagate - decides if resultType can be propagated */
2339 /*-----------------------------------------------------------------*/
2341 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2343 switch (tree->opval.op)
2360 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2361 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2362 return RESULT_TYPE_NONE;
2367 return RESULT_TYPE_NONE;
2371 return RESULT_TYPE_IFX;
2373 return RESULT_TYPE_NONE;
2377 /*-----------------------------------------------------------------*/
2378 /* getLeftResultType - gets type from left branch for propagation */
2379 /*-----------------------------------------------------------------*/
2381 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2383 switch (tree->opval.op)
2387 if (IS_PTR (LTYPE (tree)))
2388 return RESULT_TYPE_NONE;
2390 return getResultTypeFromType (LETYPE (tree));
2392 if (IS_PTR (currFunc->type->next))
2393 return RESULT_TYPE_NONE;
2395 return getResultTypeFromType (currFunc->type->next);
2397 if (!IS_ARRAY (LTYPE (tree)))
2399 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2400 return RESULT_TYPE_CHAR;
2407 /*------------------------------------------------------------------*/
2408 /* gatherImplicitVariables: assigns correct type information to */
2409 /* symbols and values created by replaceAstWithTemporary */
2410 /* and adds the symbols to the declarations list of the */
2411 /* innermost block that contains them */
2412 /*------------------------------------------------------------------*/
2414 gatherImplicitVariables (ast * tree, ast * block)
2419 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2421 /* keep track of containing scope */
2424 if (tree->type == EX_OP && tree->opval.op == '=' &&
2425 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2427 symbol *assignee = tree->left->opval.val->sym;
2429 /* special case for assignment to compiler-generated temporary variable:
2430 compute type of RHS, and set the symbol's type to match */
2431 if (assignee->type == NULL && assignee->infertype) {
2432 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2434 if (dtr != tree->right)
2437 assignee->type = copyLinkChain(TTYPE(dtr));
2438 assignee->etype = getSpec(assignee->type);
2439 SPEC_SCLS (assignee->etype) = S_AUTO;
2440 SPEC_OCLS (assignee->etype) = NULL;
2441 SPEC_EXTR (assignee->etype) = 0;
2442 SPEC_STAT (assignee->etype) = 0;
2443 SPEC_VOLATILE (assignee->etype) = 0;
2444 SPEC_ABSA (assignee->etype) = 0;
2446 wassertl(block != NULL, "implicit variable not contained in block");
2447 wassert(assignee->next == NULL);
2448 if (block != NULL) {
2449 symbol **decl = &(block->values.sym);
2452 wassert(*decl != assignee); /* should not already be in list */
2453 decl = &( (*decl)->next );
2460 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2461 tree->opval.val->type == NULL &&
2462 tree->opval.val->sym &&
2463 tree->opval.val->sym->infertype)
2465 /* fixup type of value for compiler-inferred temporary var */
2466 tree->opval.val->type = tree->opval.val->sym->type;
2467 tree->opval.val->etype = tree->opval.val->sym->etype;
2470 gatherImplicitVariables(tree->left, block);
2471 gatherImplicitVariables(tree->right, block);
2474 /*--------------------------------------------------------------------*/
2475 /* decorateType - compute type for this tree, also does type checking.*/
2476 /* This is done bottom up, since type has to flow upwards. */
2477 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2478 /* result is a char and the operand(s) are int's. */
2479 /* It also does constant folding, and parameter checking. */
2480 /*--------------------------------------------------------------------*/
2482 decorateType (ast * tree, RESULT_TYPE resultType)
2486 RESULT_TYPE resultTypeProp;
2491 /* if already has type then do nothing */
2492 if (tree->decorated)
2495 tree->decorated = 1;
2498 /* print the line */
2499 /* if not block & function */
2500 if (tree->type == EX_OP &&
2501 (tree->opval.op != FUNCTION &&
2502 tree->opval.op != BLOCK &&
2503 tree->opval.op != NULLOP))
2505 filename = tree->filename;
2506 lineno = tree->lineno;
2510 /* if any child is an error | this one is an error do nothing */
2511 if (tree->isError ||
2512 (tree->left && tree->left->isError) ||
2513 (tree->right && tree->right->isError))
2516 /*------------------------------------------------------------------*/
2517 /*----------------------------*/
2518 /* leaf has been reached */
2519 /*----------------------------*/
2520 filename = tree->filename;
2521 lineno = tree->lineno;
2522 /* if this is of type value */
2523 /* just get the type */
2524 if (tree->type == EX_VALUE)
2526 if (IS_LITERAL (tree->opval.val->etype))
2528 /* if this is a character array then declare it */
2529 if (IS_ARRAY (tree->opval.val->type))
2530 tree->opval.val = stringToSymbol (tree->opval.val);
2532 /* otherwise just copy the type information */
2533 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2537 if (tree->opval.val->sym)
2539 /* if the undefined flag is set then give error message */
2540 if (tree->opval.val->sym->undefined)
2542 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2544 TTYPE (tree) = TETYPE (tree) =
2545 tree->opval.val->type = tree->opval.val->sym->type =
2546 tree->opval.val->etype = tree->opval.val->sym->etype =
2547 copyLinkChain (INTTYPE);
2549 else if (tree->opval.val->sym->implicit)
2551 /* if implicit i.e. struct/union member then no type */
2552 TTYPE (tree) = TETYPE (tree) = NULL;
2556 /* copy the type from the value into the ast */
2557 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2559 /* and mark the symbol as referenced */
2560 tree->opval.val->sym->isref = 1;
2564 wassert(0); /* unreached: all values are literals or symbols */
2569 /* if type link for the case of cast */
2570 if (tree->type == EX_LINK)
2572 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2580 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2582 if (tree->left && tree->left->type == EX_OPERAND
2583 && (tree->left->opval.op == INC_OP
2584 || tree->left->opval.op == DEC_OP)
2585 && tree->left->left)
2587 tree->left->right = tree->left->left;
2588 tree->left->left = NULL;
2590 if (tree->right && tree->right->type == EX_OPERAND
2591 && (tree->right->opval.op == INC_OP
2592 || tree->right->opval.op == DEC_OP)
2593 && tree->right->left)
2595 tree->right->right = tree->right->left;
2596 tree->right->left = NULL;
2601 /* Before decorating the left branch we've to decide in dependence
2602 upon tree->opval.op, if resultType can be propagated */
2603 resultTypeProp = resultTypePropagate (tree, resultType);
2605 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2606 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2608 dtl = decorateType (tree->left, resultTypeProp);
2610 /* if an array node, we may need to swap branches */
2611 if (tree->opval.op == '[')
2613 /* determine which is the array & which the index */
2614 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2615 IS_INTEGRAL (LTYPE (tree)))
2617 ast *tempTree = tree->left;
2618 tree->left = tree->right;
2619 tree->right = tempTree;
2623 /* After decorating the left branch there's type information available
2624 in tree->left->?type. If the op is e.g. '=' we extract the type
2625 information from there and propagate it to the right branch. */
2626 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2628 switch (tree->opval.op)
2631 /* delay right side for '?' operator since conditional macro
2632 expansions might rely on this */
2636 /* decorate right side for CALL (parameter list) in processParms();
2637 there is resultType available */
2641 /* don't allocate string if it is a sizeof argument */
2643 dtr = decorateType (tree->right, resultTypeProp);
2647 dtr = decorateType (tree->right, resultTypeProp);
2651 /* this is to take care of situations
2652 when the tree gets rewritten */
2653 if (dtl != tree->left)
2655 if (dtr != tree->right)
2657 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2661 /* depending on type of operator do */
2663 switch (tree->opval.op)
2665 /*------------------------------------------------------------------*/
2666 /*----------------------------*/
2668 /*----------------------------*/
2671 /* first check if this is a array or a pointer */
2672 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2674 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2675 goto errorTreeReturn;
2678 /* check if the type of the idx */
2679 if (!IS_INTEGRAL (RTYPE (tree)))
2681 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2682 goto errorTreeReturn;
2685 /* if the left is an rvalue then error */
2688 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2689 goto errorTreeReturn;
2692 if (IS_LITERAL (RTYPE (tree)))
2694 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2695 int arraySize = DCL_ELEM (LTYPE (tree));
2696 if (arraySize && arrayIndex >= arraySize)
2698 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2703 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2704 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2707 /*------------------------------------------------------------------*/
2708 /*----------------------------*/
2710 /*----------------------------*/
2712 /* if this is not a structure */
2713 if (!IS_STRUCT (LTYPE (tree)))
2715 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2716 goto errorTreeReturn;
2718 TTYPE (tree) = structElemType (LTYPE (tree),
2719 (tree->right->type == EX_VALUE ?
2720 tree->right->opval.val : NULL));
2721 TETYPE (tree) = getSpec (TTYPE (tree));
2724 /*------------------------------------------------------------------*/
2725 /*----------------------------*/
2726 /* struct/union pointer */
2727 /*----------------------------*/
2729 /* if not pointer to a structure */
2730 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2732 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2733 goto errorTreeReturn;
2736 if (!IS_STRUCT (LTYPE (tree)->next))
2738 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2739 goto errorTreeReturn;
2742 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2743 (tree->right->type == EX_VALUE ?
2744 tree->right->opval.val : NULL));
2745 TETYPE (tree) = getSpec (TTYPE (tree));
2747 /* adjust the storage class */
2748 switch (DCL_TYPE(tree->left->ftype)) {
2750 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2753 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2756 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2759 SPEC_SCLS (TETYPE (tree)) = 0;
2762 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2765 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2768 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2771 SPEC_SCLS (TETYPE (tree)) = 0;
2778 /* This breaks with extern declarations, bitfields, and perhaps other */
2779 /* cases (gcse). Let's leave this optimization disabled for now and */
2780 /* ponder if there's a safe way to do this. -- EEP */
2782 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2783 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2785 /* If defined struct type at addr var
2786 then rewrite (&struct var)->member
2788 and define membertype at (addr+offsetof(struct var,member)) temp
2791 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2792 AST_SYMBOL(tree->right));
2794 sym = newSymbol(genSymName (0), 0);
2795 sym->type = TTYPE (tree);
2796 sym->etype = getSpec(sym->type);
2797 sym->lineDef = tree->lineno;
2800 SPEC_STAT (sym->etype) = 1;
2801 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2803 SPEC_ABSA(sym->etype) = 1;
2804 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2807 AST_VALUE (tree) = symbolVal(sym);
2810 tree->type = EX_VALUE;
2818 /*------------------------------------------------------------------*/
2819 /*----------------------------*/
2820 /* ++/-- operation */
2821 /*----------------------------*/
2825 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2826 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2827 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2828 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2837 /*------------------------------------------------------------------*/
2838 /*----------------------------*/
2840 /*----------------------------*/
2841 case '&': /* can be unary */
2842 /* if right is NULL then unary operation */
2843 if (tree->right) /* not an unary operation */
2846 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2848 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2849 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2850 printTypeChain (LTYPE (tree), stderr);
2851 fprintf (stderr, ",");
2852 printTypeChain (RTYPE (tree), stderr);
2853 fprintf (stderr, "\n");
2854 goto errorTreeReturn;
2857 /* if they are both literal */
2858 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2860 tree->type = EX_VALUE;
2861 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2862 valFromType (RETYPE (tree)), '&');
2864 tree->right = tree->left = NULL;
2865 TETYPE (tree) = tree->opval.val->etype;
2866 TTYPE (tree) = tree->opval.val->type;
2870 /* see if this is a GETHBIT operation if yes
2873 ast *otree = optimizeGetHbit (tree, resultType);
2876 return decorateType (otree, RESULT_TYPE_NONE);
2879 /* see if this is a GETABIT operation if yes
2882 ast *otree = optimizeGetAbit (tree, resultType);
2885 return decorateType (otree, RESULT_TYPE_NONE);
2888 /* see if this is a GETBYTE operation if yes
2891 ast *otree = optimizeGetByte (tree, resultType);
2894 return decorateType (otree, RESULT_TYPE_NONE);
2897 /* see if this is a GETWORD operation if yes
2900 ast *otree = optimizeGetWord (tree, resultType);
2903 return decorateType (otree, RESULT_TYPE_NONE);
2906 /* if left is a literal exchange left & right */
2907 if (IS_LITERAL (LTYPE (tree)))
2909 ast *tTree = tree->left;
2910 tree->left = tree->right;
2911 tree->right = tTree;
2914 /* if right is a literal and */
2915 /* we can find a 2nd literal in an and-tree then */
2916 /* rearrange the tree */
2917 if (IS_LITERAL (RTYPE (tree)))
2920 ast *litTree = searchLitOp (tree, &parent, "&");
2924 ast *tTree = litTree->left;
2925 litTree->left = tree->right;
2926 tree->right = tTree;
2927 /* both operands in litTree are literal now */
2928 decorateType (parent, resultType);
2932 LRVAL (tree) = RRVAL (tree) = 1;
2934 TTYPE (tree) = computeType (LTYPE (tree),
2938 TETYPE (tree) = getSpec (TTYPE (tree));
2943 /*------------------------------------------------------------------*/
2944 /*----------------------------*/
2946 /*----------------------------*/
2947 p = newLink (DECLARATOR);
2948 /* if bit field then error */
2949 if (IS_BITVAR (tree->left->etype))
2951 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2952 goto errorTreeReturn;
2955 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2957 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2958 goto errorTreeReturn;
2961 if (IS_FUNC (LTYPE (tree)))
2963 // this ought to be ignored
2964 return (tree->left);
2967 if (IS_LITERAL(LTYPE(tree)))
2969 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2970 goto errorTreeReturn;
2975 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2976 goto errorTreeReturn;
2979 DCL_TYPE (p) = POINTER;
2980 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2981 DCL_TYPE (p) = CPOINTER;
2982 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2983 DCL_TYPE (p) = FPOINTER;
2984 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2985 DCL_TYPE (p) = PPOINTER;
2986 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2987 DCL_TYPE (p) = IPOINTER;
2988 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2989 DCL_TYPE (p) = EEPPOINTER;
2990 else if (SPEC_OCLS(tree->left->etype))
2991 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2993 DCL_TYPE (p) = POINTER;
2995 if (IS_AST_SYM_VALUE (tree->left))
2997 AST_SYMBOL (tree->left)->addrtaken = 1;
2998 AST_SYMBOL (tree->left)->allocreq = 1;
3001 p->next = LTYPE (tree);
3003 TETYPE (tree) = getSpec (TTYPE (tree));
3008 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
3009 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
3011 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
3012 AST_SYMBOL(tree->left->right));
3013 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
3014 valueFromLit(element->offset));
3017 tree->type = EX_VALUE;
3018 tree->values.literalFromCast = 1;
3024 /*------------------------------------------------------------------*/
3025 /*----------------------------*/
3027 /*----------------------------*/
3029 /* if the rewrite succeeds then don't go any further */
3031 ast *wtree = optimizeRRCRLC (tree);
3033 return decorateType (wtree, RESULT_TYPE_NONE);
3035 wtree = optimizeSWAP (tree);
3037 return decorateType (wtree, RESULT_TYPE_NONE);
3040 /* if left is a literal exchange left & right */
3041 if (IS_LITERAL (LTYPE (tree)))
3043 ast *tTree = tree->left;
3044 tree->left = tree->right;
3045 tree->right = tTree;
3048 /* if right is a literal and */
3049 /* we can find a 2nd literal in an or-tree then */
3050 /* rearrange the tree */
3051 if (IS_LITERAL (RTYPE (tree)))
3054 ast *litTree = searchLitOp (tree, &parent, "|");
3058 ast *tTree = litTree->left;
3059 litTree->left = tree->right;
3060 tree->right = tTree;
3061 /* both operands in tTree are literal now */
3062 decorateType (parent, resultType);
3067 /*------------------------------------------------------------------*/
3068 /*----------------------------*/
3070 /*----------------------------*/
3072 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3074 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3075 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3076 printTypeChain (LTYPE (tree), stderr);
3077 fprintf (stderr, ",");
3078 printTypeChain (RTYPE (tree), stderr);
3079 fprintf (stderr, "\n");
3080 goto errorTreeReturn;
3083 /* if they are both literal then rewrite the tree */
3084 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3086 tree->type = EX_VALUE;
3087 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3088 valFromType (RETYPE (tree)),
3090 tree->right = tree->left = NULL;
3091 TETYPE (tree) = tree->opval.val->etype;
3092 TTYPE (tree) = tree->opval.val->type;
3096 /* if left is a literal exchange left & right */
3097 if (IS_LITERAL (LTYPE (tree)))
3099 ast *tTree = tree->left;
3100 tree->left = tree->right;
3101 tree->right = tTree;
3104 /* if right is a literal and */
3105 /* we can find a 2nd literal in a xor-tree then */
3106 /* rearrange the tree */
3107 if (IS_LITERAL (RTYPE (tree)) &&
3108 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3111 ast *litTree = searchLitOp (tree, &parent, "^");
3115 ast *tTree = litTree->left;
3116 litTree->left = tree->right;
3117 tree->right = tTree;
3118 /* both operands in litTree are literal now */
3119 decorateType (parent, resultType);
3123 LRVAL (tree) = RRVAL (tree) = 1;
3125 TTYPE (tree) = computeType (LTYPE (tree),
3129 TETYPE (tree) = getSpec (TTYPE (tree));
3133 /*------------------------------------------------------------------*/
3134 /*----------------------------*/
3136 /*----------------------------*/
3138 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3140 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3141 goto errorTreeReturn;
3143 /* if they are both literal then */
3144 /* rewrite the tree */
3145 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3147 tree->type = EX_VALUE;
3148 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3149 valFromType (RETYPE (tree)));
3150 tree->right = tree->left = NULL;
3151 TETYPE (tree) = getSpec (TTYPE (tree) =
3152 tree->opval.val->type);
3156 LRVAL (tree) = RRVAL (tree) = 1;
3158 TETYPE (tree) = getSpec (TTYPE (tree) =
3159 computeType (LTYPE (tree),
3164 /* if right is a literal and */
3165 /* left is also a division by a literal then */
3166 /* rearrange the tree */
3167 if (IS_LITERAL (RTYPE (tree))
3168 /* avoid infinite loop */
3169 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3172 ast *litTree = searchLitOp (tree, &parent, "/");
3175 if (IS_LITERAL (RTYPE (litTree)))
3179 litTree->right = newNode ('*',
3181 copyAst (tree->right));
3182 litTree->right->filename = tree->filename;
3183 litTree->right->lineno = tree->lineno;
3185 tree->right->opval.val = constCharVal (1);
3186 decorateType (parent, resultType);
3190 /* litTree->left is literal: no gcse possible.
3191 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3192 this would cause an infinit loop. */
3193 parent->decorated = 1;
3194 decorateType (litTree, resultType);
3201 /*------------------------------------------------------------------*/
3202 /*----------------------------*/
3204 /*----------------------------*/
3206 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3208 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3209 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3210 printTypeChain (LTYPE (tree), stderr);
3211 fprintf (stderr, ",");
3212 printTypeChain (RTYPE (tree), stderr);
3213 fprintf (stderr, "\n");
3214 goto errorTreeReturn;
3216 /* if they are both literal then */
3217 /* rewrite the tree */
3218 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3220 tree->type = EX_VALUE;
3221 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3222 valFromType (RETYPE (tree)));
3223 tree->right = tree->left = NULL;
3224 TETYPE (tree) = getSpec (TTYPE (tree) =
3225 tree->opval.val->type);
3228 LRVAL (tree) = RRVAL (tree) = 1;
3229 TETYPE (tree) = getSpec (TTYPE (tree) =
3230 computeType (LTYPE (tree),
3236 /*------------------------------------------------------------------*/
3237 /*----------------------------*/
3238 /* address dereference */
3239 /*----------------------------*/
3240 case '*': /* can be unary : if right is null then unary operation */
3243 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3245 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3246 goto errorTreeReturn;
3251 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3252 goto errorTreeReturn;
3254 if (IS_ADDRESS_OF_OP(tree->left))
3256 /* replace *&obj with obj */
3257 return tree->left->left;
3259 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3260 TETYPE (tree) = getSpec (TTYPE (tree));
3261 /* adjust the storage class */
3262 switch (DCL_TYPE(tree->left->ftype)) {
3264 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3267 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3270 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3273 SPEC_SCLS (TETYPE (tree)) = 0;
3276 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3279 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3282 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3285 SPEC_SCLS (TETYPE (tree)) = 0;
3294 /*------------------------------------------------------------------*/
3295 /*----------------------------*/
3296 /* multiplication */
3297 /*----------------------------*/
3298 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3300 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3301 goto errorTreeReturn;
3304 /* if they are both literal then */
3305 /* rewrite the tree */
3306 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3308 tree->type = EX_VALUE;
3309 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3310 valFromType (RETYPE (tree)));
3311 tree->right = tree->left = NULL;
3312 TETYPE (tree) = getSpec (TTYPE (tree) =
3313 tree->opval.val->type);
3317 /* if left is a literal exchange left & right */
3318 if (IS_LITERAL (LTYPE (tree)))
3320 ast *tTree = tree->left;
3321 tree->left = tree->right;
3322 tree->right = tTree;
3325 /* if right is a literal and */
3326 /* we can find a 2nd literal in a mul-tree then */
3327 /* rearrange the tree */
3328 if (IS_LITERAL (RTYPE (tree)))
3331 ast *litTree = searchLitOp (tree, &parent, "*");
3335 ast *tTree = litTree->left;
3336 litTree->left = tree->right;
3337 tree->right = tTree;
3338 /* both operands in litTree are literal now */
3339 decorateType (parent, resultType);
3343 LRVAL (tree) = RRVAL (tree) = 1;
3344 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3345 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3346 TETYPE (tree) = getSpec (TTYPE (tree) =
3347 computeType (LTYPE (tree),
3354 /*------------------------------------------------------------------*/
3355 /*----------------------------*/
3356 /* unary '+' operator */
3357 /*----------------------------*/
3362 if (!IS_ARITHMETIC (LTYPE (tree)))
3364 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3365 goto errorTreeReturn;
3368 /* if left is a literal then do it */
3369 if (IS_LITERAL (LTYPE (tree)))
3371 tree->type = EX_VALUE;
3372 tree->opval.val = valFromType (LETYPE (tree));
3374 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3378 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3382 /*------------------------------------------------------------------*/
3383 /*----------------------------*/
3385 /*----------------------------*/
3387 /* this is not a unary operation */
3388 /* if both pointers then problem */
3389 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3390 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3392 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3393 goto errorTreeReturn;
3396 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3397 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3399 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3400 goto errorTreeReturn;
3403 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3404 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3406 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3407 goto errorTreeReturn;
3409 /* if they are both literal then */
3410 /* rewrite the tree */
3411 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3413 tree->type = EX_VALUE;
3414 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3415 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3416 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3417 valFromType (RETYPE (tree)));
3418 tree->right = tree->left = NULL;
3419 TETYPE (tree) = getSpec (TTYPE (tree) =
3420 tree->opval.val->type);
3424 /* if the right is a pointer or left is a literal
3425 xchange left & right */
3426 if (IS_ARRAY (RTYPE (tree)) ||
3427 IS_PTR (RTYPE (tree)) ||
3428 IS_LITERAL (LTYPE (tree)))
3430 ast *tTree = tree->left;
3431 tree->left = tree->right;
3432 tree->right = tTree;
3435 /* if right is a literal and */
3436 /* left is also an addition/subtraction with a literal then */
3437 /* rearrange the tree */
3438 if (IS_LITERAL (RTYPE (tree)))
3440 ast *litTree, *parent;
3441 litTree = searchLitOp (tree, &parent, "+-");
3444 if (litTree->opval.op == '+')
3448 ast *tTree = litTree->left;
3449 litTree->left = tree->right;
3450 tree->right = tree->left;
3453 else if (litTree->opval.op == '-')
3455 if (IS_LITERAL (RTYPE (litTree)))
3459 ast *tTree = litTree->left;
3460 litTree->left = tree->right;
3461 tree->right = tTree;
3467 ast *tTree = litTree->right;
3468 litTree->right = tree->right;
3469 tree->right = tTree;
3470 litTree->opval.op = '+';
3471 tree->opval.op = '-';
3474 decorateType (parent, resultType);
3478 LRVAL (tree) = RRVAL (tree) = 1;
3479 /* if the left is a pointer */
3480 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3481 TETYPE (tree) = getSpec (TTYPE (tree) =
3485 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3486 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3487 TETYPE (tree) = getSpec (TTYPE (tree) =
3488 computeType (LTYPE (tree),
3496 /*------------------------------------------------------------------*/
3497 /*----------------------------*/
3499 /*----------------------------*/
3500 case '-': /* can be unary */
3501 /* if right is null then unary */
3505 if (!IS_ARITHMETIC (LTYPE (tree)))
3507 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3508 goto errorTreeReturn;
3511 /* if left is a literal then do it */
3512 if (IS_LITERAL (LTYPE (tree)))
3514 tree->type = EX_VALUE;
3515 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3517 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3520 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3521 TETYPE (tree) = getSpec (TTYPE (tree) =
3522 computeType (LTYPE (tree),
3530 /*------------------------------------------------------------------*/
3531 /*----------------------------*/
3533 /*----------------------------*/
3535 if (!(IS_PTR (LTYPE (tree)) ||
3536 IS_ARRAY (LTYPE (tree)) ||
3537 IS_ARITHMETIC (LTYPE (tree))))
3539 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3540 goto errorTreeReturn;
3543 if (!(IS_PTR (RTYPE (tree)) ||
3544 IS_ARRAY (RTYPE (tree)) ||
3545 IS_ARITHMETIC (RTYPE (tree))))
3547 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3548 goto errorTreeReturn;
3551 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3552 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3553 IS_INTEGRAL (RTYPE (tree))))
3555 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3556 goto errorTreeReturn;
3559 /* if they are both literal then */
3560 /* rewrite the tree */
3561 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3563 tree->type = EX_VALUE;
3564 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3565 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3566 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3567 valFromType (RETYPE (tree)));
3568 tree->right = tree->left = NULL;
3569 TETYPE (tree) = getSpec (TTYPE (tree) =
3570 tree->opval.val->type);
3574 /* if the left & right are equal then zero */
3575 if (isAstEqual (tree->left, tree->right))
3577 tree->type = EX_VALUE;
3578 tree->left = tree->right = NULL;
3579 tree->opval.val = constCharVal (0);
3580 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3584 /* if both of them are pointers or arrays then */
3585 /* the result is going to be an integer */
3586 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3587 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3588 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3590 /* if only the left is a pointer */
3591 /* then result is a pointer */
3592 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3593 TETYPE (tree) = getSpec (TTYPE (tree) =
3597 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3598 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3600 TETYPE (tree) = getSpec (TTYPE (tree) =
3601 computeType (LTYPE (tree),
3607 LRVAL (tree) = RRVAL (tree) = 1;
3609 /* if right is a literal and */
3610 /* left is also an addition/subtraction with a literal then */
3611 /* rearrange the tree */
3612 if (IS_LITERAL (RTYPE (tree))
3613 /* avoid infinite loop */
3614 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3616 ast *litTree, *litParent;
3617 litTree = searchLitOp (tree, &litParent, "+-");
3620 if (litTree->opval.op == '+')
3624 ast *tTree = litTree->left;
3625 litTree->left = litTree->right;
3626 litTree->right = tree->right;
3627 tree->right = tTree;
3628 tree->opval.op = '+';
3629 litTree->opval.op = '-';
3631 else if (litTree->opval.op == '-')
3633 if (IS_LITERAL (RTYPE (litTree)))
3637 ast *tTree = litTree->left;
3638 litTree->left = tree->right;
3639 tree->right = litParent->left;
3640 litParent->left = tTree;
3641 litTree->opval.op = '+';
3643 tree->decorated = 0;
3644 decorateType (tree, resultType);
3650 ast *tTree = litTree->right;
3651 litTree->right = tree->right;
3652 tree->right = tTree;
3655 decorateType (litParent, resultType);
3660 /*------------------------------------------------------------------*/
3661 /*----------------------------*/
3663 /*----------------------------*/
3665 /* can be only integral type */
3666 if (!IS_INTEGRAL (LTYPE (tree)))
3668 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3669 goto errorTreeReturn;
3672 /* if left is a literal then do it */
3673 if (IS_LITERAL (LTYPE (tree)))
3675 tree->type = EX_VALUE;
3676 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3678 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3679 return addCast (tree, resultTypeProp, TRUE);
3682 if (resultType == RESULT_TYPE_BIT &&
3683 IS_UNSIGNED (tree->left->etype) &&
3684 getSize (tree->left->etype) < INTSIZE)
3686 /* promotion rules are responsible for this strange result:
3687 bit -> int -> ~int -> bit
3688 uchar -> int -> ~int -> bit
3690 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3692 /* optimize bit-result, even if we optimize a buggy source */
3693 tree->type = EX_VALUE;
3694 tree->opval.val = constCharVal (1);
3697 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3699 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3702 /*------------------------------------------------------------------*/
3703 /*----------------------------*/
3705 /*----------------------------*/
3707 /* can be pointer */
3708 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3709 !IS_PTR (LTYPE (tree)) &&
3710 !IS_ARRAY (LTYPE (tree)))
3712 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3713 goto errorTreeReturn;
3716 /* if left is another '!' */
3717 if (IS_AST_NOT_OPER (tree->left))
3719 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3721 /* replace double '!!X' by 'X' */
3722 return tree->left->left;
3724 /* remove double '!!X' by 'X ? 1 : 0' */
3725 tree->opval.op = '?';
3726 tree->left = tree->left->left;
3727 tree->right = newNode (':',
3728 newAst_VALUE (constCharVal (1)),
3729 newAst_VALUE (constCharVal (0)));
3730 tree->right->filename = tree->filename;
3731 tree->right->lineno = tree->lineno;
3732 tree->decorated = 0;
3733 return decorateType (tree, resultType);
3736 /* if left is a literal then do it */
3737 if (IS_LITERAL (LTYPE (tree)))
3739 tree->type = EX_VALUE;
3740 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3742 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3746 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3749 /*------------------------------------------------------------------*/
3750 /*----------------------------*/
3752 /*----------------------------*/
3756 TTYPE (tree) = LTYPE (tree);
3757 TETYPE (tree) = LETYPE (tree);
3762 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3766 TTYPE (tree) = TETYPE (tree) = newCharLink();
3770 TTYPE (tree) = TETYPE (tree) = newIntLink();
3775 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3777 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3778 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3779 printTypeChain (LTYPE (tree), stderr);
3780 fprintf (stderr, ",");
3781 printTypeChain (RTYPE (tree), stderr);
3782 fprintf (stderr, "\n");
3783 goto errorTreeReturn;
3786 /* make smaller type only if it's a LEFT_OP */
3787 if (tree->opval.op == LEFT_OP)
3788 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3790 /* if they are both literal then */
3791 /* rewrite the tree */
3792 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3794 tree->type = EX_VALUE;
3795 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3796 valFromType (RETYPE (tree)),
3797 (tree->opval.op == LEFT_OP ? 1 : 0));
3798 tree->right = tree->left = NULL;
3799 TETYPE (tree) = getSpec (TTYPE (tree) =
3800 tree->opval.val->type);
3804 /* see if this is a GETBYTE operation if yes
3807 ast *otree = optimizeGetByte (tree, resultType);
3810 return decorateType (otree, RESULT_TYPE_NONE);
3813 /* see if this is a GETWORD operation if yes
3816 ast *otree = optimizeGetWord (tree, resultType);
3819 return decorateType (otree, RESULT_TYPE_NONE);
3822 LRVAL (tree) = RRVAL (tree) = 1;
3823 if (tree->opval.op == LEFT_OP)
3825 TETYPE (tree) = getSpec (TTYPE (tree) =
3826 computeType (LTYPE (tree),
3833 /* no promotion necessary */
3834 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3835 if (IS_LITERAL (TTYPE (tree)))
3836 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3839 /* if only the right side is a literal & we are
3840 shifting more than size of the left operand then zero */
3841 if (IS_LITERAL (RTYPE (tree)) &&
3842 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3843 (getSize (TETYPE (tree)) * 8))
3845 if (tree->opval.op==LEFT_OP ||
3846 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3848 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3849 (tree->opval.op == LEFT_OP ? "left" : "right"));
3850 tree->type = EX_VALUE;
3851 tree->left = tree->right = NULL;
3852 tree->opval.val = constCharVal (0);
3853 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3860 /*------------------------------------------------------------------*/
3861 /*----------------------------*/
3863 /*----------------------------*/
3864 case CAST: /* change the type */
3865 /* cannot cast to an aggregate type */
3866 if (IS_AGGREGATE (LTYPE (tree)))
3868 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3869 goto errorTreeReturn;
3872 /* make sure the type is complete and sane */
3873 changePointer(LTYPE(tree));
3874 checkTypeSanity(LETYPE(tree), "(cast)");
3877 /* if 'from' and 'to' are the same remove the superfluous cast,
3878 * this helps other optimizations */
3879 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3881 /* mark that the explicit cast has been removed,
3882 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3883 tree->right->values.removedCast = 1;
3887 /* If code memory is read only, then pointers to code memory */
3888 /* implicitly point to constants -- make this explicit */
3890 sym_link *t = LTYPE(tree);
3891 while (t && t->next)
3893 if (IS_CODEPTR(t) && port->mem.code_ro)
3895 if (IS_SPEC(t->next))
3896 SPEC_CONST (t->next) = 1;
3898 DCL_PTR_CONST (t->next) = 1;
3905 /* if the right is a literal replace the tree */
3906 if (IS_LITERAL (RETYPE (tree))) {
3907 if (!IS_PTR (LTYPE (tree))) {
3908 tree->type = EX_VALUE;
3910 valCastLiteral (LTYPE (tree),
3911 floatFromVal (valFromType (RETYPE (tree))));
3914 TTYPE (tree) = tree->opval.val->type;
3915 tree->values.literalFromCast = 1;
3916 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3917 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3918 sym_link *rest = LTYPE(tree)->next;
3919 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3920 TTYPE(tree) = newLink(DECLARATOR);
3921 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3922 TTYPE(tree)->next = rest;
3923 tree->left->opval.lnk = TTYPE(tree);
3926 TTYPE (tree) = LTYPE (tree);
3930 TTYPE (tree) = LTYPE (tree);
3934 #if 0 // this is already checked, now this could be explicit
3935 /* if pointer to struct then check names */
3936 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3937 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3938 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3940 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3941 SPEC_STRUCT(LETYPE(tree))->tag);
3944 if (IS_ADDRESS_OF_OP(tree->right)
3945 && IS_AST_SYM_VALUE (tree->right->left)
3946 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3948 symbol * sym = AST_SYMBOL (tree->right->left);
3949 unsigned int gptype = 0;
3950 unsigned int addr = SPEC_ADDR (sym->etype);
3952 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3953 || TARGET_IS_PIC16) )
3955 switch (SPEC_SCLS (sym->etype))
3958 gptype = GPTYPE_CODE;
3961 gptype = GPTYPE_FAR;
3965 gptype = GPTYPE_NEAR;
3968 gptype = GPTYPE_XSTACK;
3973 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3974 gptype = GPTYPE_NEAR;
3976 addr |= gptype << (8*(GPTRSIZE - 1));
3979 tree->type = EX_VALUE;
3981 valCastLiteral (LTYPE (tree), addr);
3982 TTYPE (tree) = tree->opval.val->type;
3983 TETYPE (tree) = getSpec (TTYPE (tree));
3986 tree->values.literalFromCast = 1;
3990 /* handle offsetof macro: */
3991 /* #define offsetof(TYPE, MEMBER) \ */
3992 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3993 if (IS_ADDRESS_OF_OP(tree->right)
3994 && IS_AST_OP (tree->right->left)
3995 && tree->right->left->opval.op == PTR_OP
3996 && IS_AST_OP (tree->right->left->left)
3997 && tree->right->left->left->opval.op == CAST
3998 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
4000 symbol *element = getStructElement (
4001 SPEC_STRUCT (LETYPE(tree->right->left)),
4002 AST_SYMBOL(tree->right->left->right)
4006 tree->type = EX_VALUE;
4007 tree->opval.val = valCastLiteral (
4010 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
4013 TTYPE (tree) = tree->opval.val->type;
4014 TETYPE (tree) = getSpec (TTYPE (tree));
4021 /* if the right is a literal replace the tree */
4022 if (IS_LITERAL (RETYPE (tree))) {
4024 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
4025 /* rewrite (type *)litaddr
4027 and define type at litaddr temp
4028 (but only if type's storage class is not generic)
4030 ast *newTree = newNode ('&', NULL, NULL);
4033 TTYPE (newTree) = LTYPE (tree);
4034 TETYPE (newTree) = getSpec(LTYPE (tree));
4036 /* define a global symbol at the casted address*/
4037 sym = newSymbol(genSymName (0), 0);
4038 sym->type = LTYPE (tree)->next;
4040 sym->type = newLink (V_VOID);
4041 sym->etype = getSpec(sym->type);
4042 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4043 sym->lineDef = tree->lineno;
4046 SPEC_STAT (sym->etype) = 1;
4047 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4048 SPEC_ABSA(sym->etype) = 1;
4049 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4052 newTree->left = newAst_VALUE(symbolVal(sym));
4053 newTree->left->filename = tree->filename;
4054 newTree->left->lineno = tree->lineno;
4055 LTYPE (newTree) = sym->type;
4056 LETYPE (newTree) = sym->etype;
4057 LLVAL (newTree) = 1;
4058 LRVAL (newTree) = 0;
4059 TLVAL (newTree) = 1;
4063 if (!IS_PTR (LTYPE (tree))) {
4064 tree->type = EX_VALUE;
4066 valCastLiteral (LTYPE (tree),
4067 floatFromVal (valFromType (RTYPE (tree))));
4068 TTYPE (tree) = tree->opval.val->type;
4071 tree->values.literalFromCast = 1;
4072 TETYPE (tree) = getSpec (TTYPE (tree));
4076 TTYPE (tree) = LTYPE (tree);
4080 TETYPE (tree) = getSpec (TTYPE (tree));
4084 /*------------------------------------------------------------------*/
4085 /*----------------------------*/
4086 /* logical &&, || */
4087 /*----------------------------*/
4090 /* each must be arithmetic type or be a pointer */
4091 if (!IS_PTR (LTYPE (tree)) &&
4092 !IS_ARRAY (LTYPE (tree)) &&
4093 !IS_INTEGRAL (LTYPE (tree)))
4095 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4096 goto errorTreeReturn;
4099 if (!IS_PTR (RTYPE (tree)) &&
4100 !IS_ARRAY (RTYPE (tree)) &&
4101 !IS_INTEGRAL (RTYPE (tree)))
4103 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4104 goto errorTreeReturn;
4106 /* if they are both literal then */
4107 /* rewrite the tree */
4108 if (IS_LITERAL (RTYPE (tree)) &&
4109 IS_LITERAL (LTYPE (tree)))
4111 tree->type = EX_VALUE;
4112 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4113 valFromType (RTYPE (tree)),
4115 tree->right = tree->left = NULL;
4116 TETYPE (tree) = getSpec (TTYPE (tree) =
4117 tree->opval.val->type);
4120 LRVAL (tree) = RRVAL (tree) = 1;
4121 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4124 /*------------------------------------------------------------------*/
4125 /*----------------------------*/
4126 /* comparison operators */
4127 /*----------------------------*/
4135 ast *lt = optimizeCompare (tree);
4141 /* if they are pointers they must be castable */
4142 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4144 if (tree->opval.op==EQ_OP &&
4145 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4146 // we cannot cast a gptr to a !gptr: switch the leaves
4147 struct ast *s=tree->left;
4148 tree->left=tree->right;
4151 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4153 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4154 fprintf (stderr, "comparing type ");
4155 printTypeChain (LTYPE (tree), stderr);
4156 fprintf (stderr, "to type ");
4157 printTypeChain (RTYPE (tree), stderr);
4158 fprintf (stderr, "\n");
4159 goto errorTreeReturn;
4162 /* else they should be promotable to one another */
4165 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4166 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4168 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4170 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4171 fprintf (stderr, "comparing type ");
4172 printTypeChain (LTYPE (tree), stderr);
4173 fprintf (stderr, "to type ");
4174 printTypeChain (RTYPE (tree), stderr);
4175 fprintf (stderr, "\n");
4176 goto errorTreeReturn;
4181 CCR_RESULT ccr_result = CCR_OK;
4183 /* if left is integral and right is literal
4184 then check constant range */
4185 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4186 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4187 tree->opval.op, FALSE);
4188 if (ccr_result == CCR_OK &&
4189 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4190 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4191 tree->opval.op, TRUE);
4194 case CCR_ALWAYS_TRUE:
4195 case CCR_ALWAYS_FALSE:
4196 if (!options.lessPedantic)
4197 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4198 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4199 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4206 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4207 if (tree->opval.op == '>' &&
4208 SPEC_USIGN(LETYPE(tree)) &&
4209 IS_LITERAL(RTYPE(tree)) &&
4210 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4212 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4214 /* the parent is an ifx: */
4215 /* if (unsigned value) */
4219 /* (unsigned value) ? 1 : 0 */
4220 tree->opval.op = '?';
4221 tree->right = newNode (':',
4222 newAst_VALUE (constCharVal (1)),
4223 tree->right); /* val 0 */
4224 tree->right->filename = tree->filename;
4225 tree->right->lineno = tree->lineno;
4226 tree->right->left->filename = tree->filename;
4227 tree->right->left->lineno = tree->lineno;
4228 tree->decorated = 0;
4229 return decorateType (tree, resultType);
4232 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4233 if (IS_LITERAL(RTYPE(tree)) &&
4234 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4235 tree->opval.op == EQ_OP &&
4236 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4238 tree->opval.op = '!';
4240 tree->decorated = 0;
4241 return decorateType (tree, resultType);
4244 /* if they are both literal then */
4245 /* rewrite the tree */
4246 if (IS_LITERAL (RTYPE (tree)) &&
4247 IS_LITERAL (LTYPE (tree)))
4249 tree->type = EX_VALUE;
4250 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4251 valFromType (RETYPE (tree)),
4253 tree->right = tree->left = NULL;
4254 TETYPE (tree) = getSpec (TTYPE (tree) =
4255 tree->opval.val->type);
4259 /* if one is 'signed char ' and the other one is 'unsigned char' */
4260 /* it's necessary to promote to int */
4261 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4262 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4264 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4265 if it's possible to use a 'signed char' */
4267 /* is left a 'unsigned char'? */
4268 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4269 /* the value range of a 'unsigned char' is 0...255;
4270 if the actual value is < 128 it can be changed to signed */
4271 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4273 /* now we've got 2 'signed char'! */
4274 SPEC_USIGN (RETYPE (tree)) = 0;
4276 /* same test for the left operand: */
4277 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4278 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4280 SPEC_USIGN (LETYPE (tree)) = 0;
4284 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4285 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4286 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4290 LRVAL (tree) = RRVAL (tree) = 1;
4291 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4293 /* condition transformations */
4295 unsigned transformedOp = 0;
4297 switch (tree->opval.op)
4299 case '<': /* transform (a < b) to !(a >= b) */
4301 transformedOp = GE_OP;
4303 case '>': /* transform (a > b) to !(a <= b) */
4305 transformedOp = LE_OP;
4307 case LE_OP: /* transform (a <= b) to !(a > b) */
4309 transformedOp = '>';
4311 case GE_OP: /* transform (a >= b) to !(a < b) */
4313 transformedOp = '<';
4315 case NE_OP: /* transform (a != b) to !(a == b) */
4317 transformedOp = EQ_OP;
4319 case EQ_OP: /* transform (a == b) to !(a != b) */
4321 transformedOp = NE_OP;
4328 tree->opval.op = transformedOp;
4329 tree->decorated = 0;
4330 tree = newNode ('!', tree, NULL);
4331 tree->filename = tree->left->filename;
4332 tree->lineno = tree->left->lineno;
4333 return decorateType (tree, resultType);
4339 /*------------------------------------------------------------------*/
4340 /*----------------------------*/
4342 /*----------------------------*/
4343 case SIZEOF: /* evaluate wihout code generation */
4344 /* change the type to a integer */
4346 int size = getSize (tree->right->ftype);
4348 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4349 if (!size && !IS_VOID(tree->right->ftype))
4350 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4352 tree->type = EX_VALUE;
4353 tree->opval.val = constVal (buffer);
4354 tree->right = tree->left = NULL;
4355 TETYPE (tree) = getSpec (TTYPE (tree) =
4356 tree->opval.val->type);
4360 /*------------------------------------------------------------------*/
4361 /*----------------------------*/
4363 /*----------------------------*/
4365 /* return typeof enum value */
4366 tree->type = EX_VALUE;
4369 if (IS_SPEC(tree->right->ftype)) {
4370 switch (SPEC_NOUN(tree->right->ftype)) {
4372 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4373 else typeofv = TYPEOF_INT;
4376 typeofv = TYPEOF_FLOAT;
4379 typeofv = TYPEOF_FIXED16X16;
4382 typeofv = TYPEOF_CHAR;
4385 typeofv = TYPEOF_VOID;
4388 typeofv = TYPEOF_STRUCT;
4391 typeofv = TYPEOF_BITFIELD;
4394 typeofv = TYPEOF_BIT;
4397 typeofv = TYPEOF_SBIT;
4403 switch (DCL_TYPE(tree->right->ftype)) {
4405 typeofv = TYPEOF_POINTER;
4408 typeofv = TYPEOF_FPOINTER;
4411 typeofv = TYPEOF_CPOINTER;
4414 typeofv = TYPEOF_GPOINTER;
4417 typeofv = TYPEOF_PPOINTER;
4420 typeofv = TYPEOF_IPOINTER;
4423 typeofv = TYPEOF_ARRAY;
4426 typeofv = TYPEOF_FUNCTION;
4432 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4433 tree->opval.val = constVal (buffer);
4434 tree->right = tree->left = NULL;
4435 TETYPE (tree) = getSpec (TTYPE (tree) =
4436 tree->opval.val->type);
4439 /*------------------------------------------------------------------*/
4440 /*----------------------------*/
4441 /* conditional operator '?' */
4442 /*----------------------------*/
4444 /* the type is value of the colon operator (on the right) */
4445 assert (IS_COLON_OP (tree->right));
4447 /* If already known then replace the tree : optimizer will do it
4448 but faster to do it here. If done before decorating tree->right
4449 this can save generating unused const strings. */
4450 if (IS_LITERAL (LTYPE (tree)))
4452 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4453 return decorateType (tree->right->left, resultTypeProp);
4455 return decorateType (tree->right->right, resultTypeProp);
4458 tree->right = decorateType (tree->right, resultTypeProp);
4460 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4461 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4463 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4464 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4466 if ((valTrue != 0) && (valFalse == 0))
4468 /* assign cond to result */
4469 tree->left->decorated = 0;
4470 return decorateType (tree->left, resultTypeProp);
4472 else if ((valTrue == 0) && (valFalse != 0))
4474 /* assign !cond to result */
4475 tree->opval.op = '!';
4476 tree->decorated = 0;
4478 return decorateType (tree, resultTypeProp);
4482 /* they have the same boolean value, make them equal */
4483 tree->right->left = tree->right->right;
4487 /* if they are equal then replace the tree */
4488 if (isAstEqual (tree->right->left, tree->right->right))
4490 return tree->right->left;
4493 TTYPE (tree) = RTYPE (tree);
4494 TETYPE (tree) = getSpec (TTYPE (tree));
4498 /* if they don't match we have a problem */
4499 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4500 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4502 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4503 goto errorTreeReturn;
4506 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4507 resultType, tree->opval.op);
4508 TETYPE (tree) = getSpec (TTYPE (tree));
4512 #if 0 // assignment operators are converted by the parser
4513 /*------------------------------------------------------------------*/
4514 /*----------------------------*/
4515 /* assignment operators */
4516 /*----------------------------*/
4519 /* for these it must be both must be integral */
4520 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4521 !IS_ARITHMETIC (RTYPE (tree)))
4523 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4524 goto errorTreeReturn;
4527 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4529 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4530 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4534 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4535 goto errorTreeReturn;
4546 /* for these it must be both must be integral */
4547 if (!IS_INTEGRAL (LTYPE (tree)) ||
4548 !IS_INTEGRAL (RTYPE (tree)))
4550 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4551 goto errorTreeReturn;
4554 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4556 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4557 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4561 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4562 goto errorTreeReturn;
4568 /*------------------------------------------------------------------*/
4569 /*----------------------------*/
4571 /*----------------------------*/
4573 if (!(IS_PTR (LTYPE (tree)) ||
4574 IS_ARITHMETIC (LTYPE (tree))))
4576 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4577 goto errorTreeReturn;
4580 if (!(IS_PTR (RTYPE (tree)) ||
4581 IS_ARITHMETIC (RTYPE (tree))))
4583 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4584 goto errorTreeReturn;
4587 TETYPE (tree) = getSpec (TTYPE (tree) =
4588 computeType (LTYPE (tree),
4593 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4594 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4598 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4599 goto errorTreeReturn;
4605 /*------------------------------------------------------------------*/
4606 /*----------------------------*/
4608 /*----------------------------*/
4610 /* this is not a unary operation */
4611 /* if both pointers then problem */
4612 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4614 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4615 goto errorTreeReturn;
4618 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4620 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4621 goto errorTreeReturn;
4624 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4626 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4627 goto errorTreeReturn;
4630 TETYPE (tree) = getSpec (TTYPE (tree) =
4631 computeType (LTYPE (tree),
4636 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4637 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4641 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4642 goto errorTreeReturn;
4645 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4646 tree->opval.op = '=';
4651 /*------------------------------------------------------------------*/
4652 /*----------------------------*/
4653 /* straight assignemnt */
4654 /*----------------------------*/
4656 /* cannot be an aggregate */
4657 if (IS_AGGREGATE (LTYPE (tree)))
4659 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4660 goto errorTreeReturn;
4663 /* they should either match or be castable */
4664 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4666 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4667 printFromToType(RTYPE(tree),LTYPE(tree));
4670 /* if the left side of the tree is of type void
4671 then report error */
4672 if (IS_VOID (LTYPE (tree)))
4674 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4675 printFromToType(RTYPE(tree), LTYPE(tree));
4678 TETYPE (tree) = getSpec (TTYPE (tree) =
4682 if (!tree->initMode ) {
4683 if (IS_CONSTANT(LTYPE(tree)))
4684 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4688 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4689 goto errorTreeReturn;
4694 /*------------------------------------------------------------------*/
4695 /*----------------------------*/
4696 /* comma operator */
4697 /*----------------------------*/
4699 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4702 /*------------------------------------------------------------------*/
4703 /*----------------------------*/
4705 /*----------------------------*/
4708 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4709 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4711 if (tree->left->opval.op == '*' && !tree->left->right)
4712 tree->left = tree->left->left;
4715 /* require a function or pointer to function */
4716 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4718 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4719 goto errorTreeReturn;
4722 /* if there are parms, make sure that
4723 parms are decorate / process / reverse only once */
4725 !tree->right->decorated)
4730 if (IS_FUNCPTR (LTYPE (tree)))
4732 functype = LTYPE (tree)->next;
4733 processFuncPtrArgs (functype);
4736 functype = LTYPE (tree);
4738 if (processParms (tree->left, FUNC_ARGS(functype),
4739 &tree->right, &parmNumber, TRUE))
4741 goto errorTreeReturn;
4744 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4745 !IFFUNC_ISBUILTIN(functype))
4747 reverseParms (tree->right);
4750 TTYPE (tree) = functype->next;
4751 TETYPE (tree) = getSpec (TTYPE (tree));
4755 /*------------------------------------------------------------------*/
4756 /*----------------------------*/
4757 /* return statement */
4758 /*----------------------------*/
4763 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4765 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4766 printFromToType (RTYPE(tree), currFunc->type->next);
4767 goto errorTreeReturn;
4770 if (IS_VOID (currFunc->type->next)
4772 !IS_VOID (RTYPE (tree)))
4774 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4775 goto errorTreeReturn;
4778 /* if there is going to be a casting required then add it */
4779 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4782 decorateType (newNode (CAST,
4783 newAst_LINK (copyLinkChain (currFunc->type->next)),
4793 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4795 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4796 goto errorTreeReturn;
4799 TTYPE (tree) = TETYPE (tree) = NULL;
4802 /*------------------------------------------------------------------*/
4803 /*----------------------------*/
4804 /* switch statement */
4805 /*----------------------------*/
4807 /* the switch value must be an integer */
4808 if (!IS_INTEGRAL (LTYPE (tree)))
4810 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4811 goto errorTreeReturn;
4814 TTYPE (tree) = TETYPE (tree) = NULL;
4817 /*------------------------------------------------------------------*/
4818 /*----------------------------*/
4820 /*----------------------------*/
4822 tree->left = backPatchLabels (tree->left,
4825 TTYPE (tree) = TETYPE (tree) = NULL;
4828 /*------------------------------------------------------------------*/
4829 /*----------------------------*/
4831 /*----------------------------*/
4834 AST_FOR (tree, initExpr) = decorateType (
4835 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4836 AST_FOR (tree, condExpr) = decorateType (
4837 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4838 AST_FOR (tree, loopExpr) = decorateType (
4839 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4841 /* if the for loop is reversible then
4842 reverse it otherwise do what we normally
4848 if (isLoopReversible (tree, &sym, &init, &end))
4849 return reverseLoop (tree, sym, init, end);
4851 return decorateType (createFor (AST_FOR (tree, trueLabel),
4852 AST_FOR (tree, continueLabel),
4853 AST_FOR (tree, falseLabel),
4854 AST_FOR (tree, condLabel),
4855 AST_FOR (tree, initExpr),
4856 AST_FOR (tree, condExpr),
4857 AST_FOR (tree, loopExpr),
4858 tree->left), RESULT_TYPE_NONE);
4861 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4862 "node PARAM shouldn't be processed here");
4863 /* but in processParams() */
4866 TTYPE (tree) = TETYPE (tree) = NULL;
4870 /* some error found this tree will be killed */
4872 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4873 tree->opval.op = NULLOP;
4879 /*-----------------------------------------------------------------*/
4880 /* sizeofOp - processes size of operation */
4881 /*-----------------------------------------------------------------*/
4883 sizeofOp (sym_link * type)
4888 /* make sure the type is complete and sane */
4889 checkTypeSanity(type, "(sizeof)");
4891 /* get the size and convert it to character */
4892 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4893 if (!size && !IS_VOID(type))
4894 werror (E_SIZEOF_INCOMPLETE_TYPE);
4896 /* now convert into value */
4897 return constVal (buff);
4901 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4902 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4903 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4904 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4905 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4906 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4907 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4909 /*-----------------------------------------------------------------*/
4910 /* backPatchLabels - change and or not operators to flow control */
4911 /*-----------------------------------------------------------------*/
4913 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4919 /* while-loops insert a label between the IFX and the condition,
4920 therefore look behind the label too */
4921 if (tree->opval.op == LABEL &&
4923 IS_ANDORNOT (tree->right))
4925 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4929 if (!(IS_ANDORNOT (tree)))
4932 /* if this an and */
4935 static int localLbl = 0;
4938 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4939 localLabel = newSymbol (buffer, NestLevel);
4941 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4943 /* if left is already a IFX then just change the if true label in that */
4944 if (!IS_IFX (tree->left))
4945 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4947 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4948 /* right is a IFX then just join */
4949 if (IS_IFX (tree->right))
4950 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4952 tree->right = createLabel (localLabel, tree->right);
4953 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4955 return newNode (NULLOP, tree->left, tree->right);
4958 /* if this is an or operation */
4961 static int localLbl = 0;
4964 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4965 localLabel = newSymbol (buffer, NestLevel);
4967 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4969 /* if left is already a IFX then just change the if true label in that */
4970 if (!IS_IFX (tree->left))
4971 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4973 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4974 /* right is a IFX then just join */
4975 if (IS_IFX (tree->right))
4976 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4978 tree->right = createLabel (localLabel, tree->right);
4979 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4981 return newNode (NULLOP, tree->left, tree->right);
4987 /* call with exchanged labels */
4988 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4990 /* if left isn't already a IFX */
4991 if (!IS_IFX (tree->left))
4993 tree->left = newNode (IFX, tree->left, NULL);
4994 tree->left->trueLabel = falseLabel;
4995 tree->left->falseLabel = trueLabel;
5002 tree->trueLabel = trueLabel;
5003 tree->falseLabel = falseLabel;
5010 /*-----------------------------------------------------------------*/
5011 /* createBlock - create expression tree for block */
5012 /*-----------------------------------------------------------------*/
5014 createBlock (symbol * decl, ast * body)
5018 /* if the block has nothing */
5022 ex = newNode (BLOCK, NULL, body);
5023 ex->values.sym = decl;
5026 ex->filename = NULL;
5031 /*-----------------------------------------------------------------*/
5032 /* createLabel - creates the expression tree for labels */
5033 /*-----------------------------------------------------------------*/
5035 createLabel (symbol * label, ast * stmnt)
5038 char name[SDCC_NAME_MAX + 1];
5041 /* must create fresh symbol if the symbol name */
5042 /* exists in the symbol table, since there can */
5043 /* be a variable with the same name as the labl */
5044 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5045 (csym->level == label->level))
5046 label = newSymbol (label->name, label->level);
5048 /* change the name before putting it in add _ */
5049 SNPRINTF(name, sizeof(name), "%s", label->name);
5051 /* put the label in the LabelSymbol table */
5052 /* but first check if a label of the same */
5054 if ((csym = findSym (LabelTab, NULL, name)))
5055 werror (E_DUPLICATE_LABEL, label->name);
5057 addSym (LabelTab, label, name, label->level, 0, 0);
5061 label->key = labelKey++;
5062 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5063 rValue->filename = NULL;
5069 /*-----------------------------------------------------------------*/
5070 /* createCase - generates the parsetree for a case statement */
5071 /*-----------------------------------------------------------------*/
5073 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5075 char caseLbl[SDCC_NAME_MAX + 1];
5079 /* if the switch statement does not exist */
5080 /* then case is out of context */
5083 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5087 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5088 /* if not a constant then error */
5089 if (!IS_LITERAL (caseVal->ftype))
5091 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5095 /* if not a integer than error */
5096 if (!IS_INTEGRAL (caseVal->ftype))
5098 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5102 /* find the end of the switch values chain */
5103 if (!(val = swStat->values.switchVals.swVals))
5104 swStat->values.switchVals.swVals = caseVal->opval.val;
5107 /* also order the cases according to value */
5109 int cVal = (int) ulFromVal (caseVal->opval.val);
5110 while (val && (int) ulFromVal (val) < cVal)
5116 /* if we reached the end then */
5119 pval->next = caseVal->opval.val;
5121 else if ((int) ulFromVal (val) == cVal)
5123 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5129 /* we found a value greater than */
5130 /* the current value we must add this */
5131 /* before the value */
5132 caseVal->opval.val->next = val;
5134 /* if this was the first in chain */
5135 if (swStat->values.switchVals.swVals == val)
5136 swStat->values.switchVals.swVals =
5139 pval->next = caseVal->opval.val;
5144 /* create the case label */
5145 SNPRINTF(caseLbl, sizeof(caseLbl),
5147 swStat->values.switchVals.swNum,
5148 (int) ulFromVal (caseVal->opval.val));
5150 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5151 rexpr->filename = 0;
5156 /*-----------------------------------------------------------------*/
5157 /* createDefault - creates the parse tree for the default statement */
5158 /*-----------------------------------------------------------------*/
5160 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5162 char defLbl[SDCC_NAME_MAX + 1];
5164 /* if the switch statement does not exist */
5165 /* then case is out of context */
5168 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5172 if (swStat->values.switchVals.swDefault)
5174 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5179 /* turn on the default flag */
5180 swStat->values.switchVals.swDefault = 1;
5182 /* create the label */
5183 SNPRINTF (defLbl, sizeof(defLbl),
5184 "_default_%d", swStat->values.switchVals.swNum);
5185 return createLabel (newSymbol (defLbl, 0), stmnt);
5188 /*-----------------------------------------------------------------*/
5189 /* createIf - creates the parsetree for the if statement */
5190 /*-----------------------------------------------------------------*/
5192 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5194 static int Lblnum = 0;
5196 symbol *ifTrue, *ifFalse, *ifEnd;
5198 /* if neither exists */
5199 if (!elseBody && !ifBody) {
5200 // if there are no side effects (i++, j() etc)
5201 if (!hasSEFcalls(condAst)) {
5206 /* create the labels */
5207 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5208 ifFalse = newSymbol (buffer, NestLevel);
5209 /* if no else body then end == false */
5214 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5215 ifEnd = newSymbol (buffer, NestLevel);
5218 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5219 ifTrue = newSymbol (buffer, NestLevel);
5223 /* attach the ifTrue label to the top of it body */
5224 ifBody = createLabel (ifTrue, ifBody);
5225 /* attach a goto end to the ifBody if else is present */
5228 ifBody = newNode (NULLOP, ifBody,
5230 newAst_VALUE (symbolVal (ifEnd)),
5232 /* put the elseLabel on the else body */
5233 elseBody = createLabel (ifFalse, elseBody);
5234 /* out the end at the end of the body */
5235 elseBody = newNode (NULLOP,
5237 createLabel (ifEnd, NULL));
5241 ifBody = newNode (NULLOP, ifBody,
5242 createLabel (ifFalse, NULL));
5244 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5245 if (IS_IFX (condAst))
5248 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5250 return newNode (NULLOP, ifTree,
5251 newNode (NULLOP, ifBody, elseBody));
5255 /*-----------------------------------------------------------------*/
5256 /* createDo - creates parse tree for do */
5259 /* _docontinue_n: */
5260 /* condition_expression +-> trueLabel -> _dobody_n */
5262 /* +-> falseLabel-> _dobreak_n */
5264 /*-----------------------------------------------------------------*/
5266 createDo (symbol * trueLabel, symbol * continueLabel,
5267 symbol * falseLabel, ast * condAst, ast * doBody)
5272 /* if the body does not exist then it is simple */
5275 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5276 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5277 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5278 doTree->trueLabel = continueLabel;
5279 doTree->falseLabel = NULL;
5281 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5285 /* otherwise we have a body */
5286 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5288 /* attach the body label to the top */
5289 doBody = createLabel (trueLabel, doBody);
5290 /* attach the continue label to end of body */
5291 doBody = newNode (NULLOP, doBody,
5292 createLabel (continueLabel, NULL));
5294 /* now put the break label at the end */
5295 if (IS_IFX (condAst))
5298 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5300 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5302 /* putting it together */
5303 return newNode (NULLOP, doBody, doTree);
5306 /*-----------------------------------------------------------------*/
5307 /* createFor - creates parse tree for 'for' statement */
5310 /* condExpr +-> trueLabel -> _forbody_n */
5312 /* +-> falseLabel-> _forbreak_n */
5315 /* _forcontinue_n: */
5317 /* goto _forcond_n ; */
5319 /*-----------------------------------------------------------------*/
5321 createFor (symbol * trueLabel, symbol * continueLabel,
5322 symbol * falseLabel, symbol * condLabel,
5323 ast * initExpr, ast * condExpr, ast * loopExpr,
5328 /* if loopexpression not present then we can generate it */
5329 /* the same way as a while */
5331 return newNode (NULLOP, initExpr,
5332 createWhile (trueLabel, continueLabel,
5333 falseLabel, condExpr, forBody));
5334 /* vanilla for statement */
5335 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5337 if (condExpr && !IS_IFX (condExpr))
5338 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5341 /* attach condition label to condition */
5342 condExpr = createLabel (condLabel, condExpr);
5344 /* attach body label to body */
5345 forBody = createLabel (trueLabel, forBody);
5347 /* attach continue to forLoop expression & attach */
5348 /* goto the forcond @ and of loopExpression */
5349 loopExpr = createLabel (continueLabel,
5353 newAst_VALUE (symbolVal (condLabel)),
5355 /* now start putting them together */
5356 forTree = newNode (NULLOP, initExpr, condExpr);
5357 forTree = newNode (NULLOP, forTree, forBody);
5358 forTree = newNode (NULLOP, forTree, loopExpr);
5359 /* finally add the break label */
5360 forTree = newNode (NULLOP, forTree,
5361 createLabel (falseLabel, NULL));
5365 /*-----------------------------------------------------------------*/
5366 /* createWhile - creates parse tree for while statement */
5367 /* the while statement will be created as follows */
5369 /* _while_continue_n: */
5370 /* condition_expression +-> trueLabel -> _while_boby_n */
5372 /* +-> falseLabel -> _while_break_n */
5373 /* _while_body_n: */
5375 /* goto _while_continue_n */
5376 /* _while_break_n: */
5377 /*-----------------------------------------------------------------*/
5379 createWhile (symbol * trueLabel, symbol * continueLabel,
5380 symbol * falseLabel, ast * condExpr, ast * whileBody)
5384 /* put the continue label */
5385 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5386 condExpr = createLabel (continueLabel, condExpr);
5387 condExpr->filename = NULL;
5388 condExpr->lineno = 0;
5390 /* put the body label in front of the body */
5391 whileBody = createLabel (trueLabel, whileBody);
5392 whileBody->filename = NULL;
5393 whileBody->lineno = 0;
5394 /* put a jump to continue at the end of the body */
5395 /* and put break label at the end of the body */
5396 whileBody = newNode (NULLOP,
5399 newAst_VALUE (symbolVal (continueLabel)),
5400 createLabel (falseLabel, NULL)));
5402 /* put it all together */
5403 if (IS_IFX (condExpr))
5404 whileTree = condExpr;
5407 whileTree = newNode (IFX, condExpr, NULL);
5408 /* put the true & false labels in place */
5409 whileTree->trueLabel = trueLabel;
5410 whileTree->falseLabel = falseLabel;
5413 return newNode (NULLOP, whileTree, whileBody);
5416 /*-----------------------------------------------------------------*/
5417 /* isShiftRightLitVal _BitAndLitVal - helper function */
5418 /*-----------------------------------------------------------------*/
5420 isShiftRightLitVal_BitAndLitVal (ast * tree)
5422 /* if this is not a bit and */
5423 if (!IS_BITAND (tree))
5426 /* will look for tree of the form
5427 ( expr >> litval2) & litval1 */
5428 if (!IS_AST_LIT_VALUE (tree->right))
5431 if (!IS_RIGHT_OP (tree->left))
5434 if (!IS_AST_LIT_VALUE (tree->left->right))
5437 return tree->left->left;
5440 /*-----------------------------------------------------------------*/
5441 /* isBitAndPowOf2 - helper function */
5442 /*-----------------------------------------------------------------*/
5444 isBitAndPow2 (ast * tree)
5446 /* if this is not a bit and */
5447 if (!IS_BITAND (tree))
5450 /* will look for tree of the form
5451 ( expr & (1 << litval) */
5452 if (!IS_AST_LIT_VALUE (tree->right))
5455 return powof2 (AST_ULONG_VALUE (tree->right));
5458 /*-----------------------------------------------------------------*/
5459 /* optimizeGetHbit - get highest order bit of the expression */
5460 /*-----------------------------------------------------------------*/
5462 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5467 expr = isShiftRightLitVal_BitAndLitVal(tree);
5470 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5471 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5472 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5475 if (!expr && (resultType == RESULT_TYPE_BIT))
5478 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5484 /* make sure the port supports GETHBIT */
5485 if (port->hasExtBitOp
5486 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5489 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5492 /*-----------------------------------------------------------------*/
5493 /* optimizeGetAbit - get a single bit of the expression */
5494 /*-----------------------------------------------------------------*/
5496 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5501 expr = isShiftRightLitVal_BitAndLitVal(tree);
5504 if (AST_ULONG_VALUE (tree->right) != 1)
5506 count = tree->left->right;
5508 if (!expr && (resultType == RESULT_TYPE_BIT))
5510 int p2 = isBitAndPow2 (tree);
5514 count = newAst_VALUE (valueFromLit (p2));
5520 /* make sure the port supports GETABIT */
5521 if (port->hasExtBitOp
5522 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5525 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5529 /*-----------------------------------------------------------------*/
5530 /* optimizeGetByte - get a byte of the expression */
5531 /*-----------------------------------------------------------------*/
5533 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5539 expr = isShiftRightLitVal_BitAndLitVal(tree);
5542 i = AST_ULONG_VALUE (tree->left->right);
5543 count = tree->left->right;
5544 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5547 if (!expr && resultType == RESULT_TYPE_CHAR)
5549 /* if this is a right shift over a multiple of 8 */
5550 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5552 i = AST_ULONG_VALUE (tree->right);
5553 count = tree->right;
5557 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5560 /* make sure the port supports GETBYTE */
5561 if (port->hasExtBitOp
5562 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5565 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5568 /*-----------------------------------------------------------------*/
5569 /* optimizeGetWord - get two bytes of the expression */
5570 /*-----------------------------------------------------------------*/
5572 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5578 expr = isShiftRightLitVal_BitAndLitVal(tree);
5581 i = AST_ULONG_VALUE (tree->left->right);
5582 count = tree->left->right;
5583 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5586 if (!expr && resultType == RESULT_TYPE_INT)
5588 /* if this is a right shift over a multiple of 8 */
5589 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5591 i = AST_ULONG_VALUE (tree->right);
5592 count = tree->right;
5596 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5599 /* make sure the port supports GETWORD */
5600 if (port->hasExtBitOp
5601 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5604 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5607 /*-----------------------------------------------------------------*/
5608 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5609 /*-----------------------------------------------------------------*/
5611 optimizeRRCRLC (ast * root)
5613 /* will look for trees of the form
5614 (?expr << 1) | (?expr >> 7) or
5615 (?expr >> 7) | (?expr << 1) will make that
5616 into a RLC : operation ..
5618 (?expr >> 1) | (?expr << 7) or
5619 (?expr << 7) | (?expr >> 1) will make that
5620 into a RRC operation
5621 note : by 7 I mean (number of bits required to hold the
5623 /* if the root operation is not a | operation then not */
5624 if (!IS_BITOR (root))
5627 /* I have to think of a better way to match patterns this sucks */
5628 /* that aside let's start looking for the first case : I use a
5629 negative check a lot to improve the efficiency */
5630 /* (?expr << 1) | (?expr >> 7) */
5631 if (IS_LEFT_OP (root->left) &&
5632 IS_RIGHT_OP (root->right))
5635 if (!SPEC_USIGN (TETYPE (root->left->left)))
5638 if (!IS_AST_LIT_VALUE (root->left->right) ||
5639 !IS_AST_LIT_VALUE (root->right->right))
5642 /* make sure it is the same expression */
5643 if (!isAstEqual (root->left->left,
5647 if (AST_ULONG_VALUE (root->left->right) != 1)
5650 if (AST_ULONG_VALUE (root->right->right) !=
5651 (getSize (TTYPE (root->left->left)) * 8 - 1))
5654 /* make sure the port supports RLC */
5655 if (port->hasExtBitOp
5656 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5659 /* whew got the first case : create the AST */
5660 return newNode (RLC, root->left->left, NULL);
5664 /* check for second case */
5665 /* (?expr >> 7) | (?expr << 1) */
5666 if (IS_LEFT_OP (root->right) &&
5667 IS_RIGHT_OP (root->left))
5670 if (!SPEC_USIGN (TETYPE (root->left->left)))
5673 if (!IS_AST_LIT_VALUE (root->left->right) ||
5674 !IS_AST_LIT_VALUE (root->right->right))
5677 /* make sure it is the same symbol */
5678 if (!isAstEqual (root->left->left,
5682 if (AST_ULONG_VALUE (root->right->right) != 1)
5685 if (AST_ULONG_VALUE (root->left->right) !=
5686 (getSize (TTYPE (root->left->left)) * 8 - 1))
5689 /* make sure the port supports RLC */
5690 if (port->hasExtBitOp
5691 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5694 /* whew got the first case : create the AST */
5695 return newNode (RLC, root->left->left, NULL);
5700 /* third case for RRC */
5701 /* (?symbol >> 1) | (?symbol << 7) */
5702 if (IS_LEFT_OP (root->right) &&
5703 IS_RIGHT_OP (root->left))
5706 if (!SPEC_USIGN (TETYPE (root->left->left)))
5709 if (!IS_AST_LIT_VALUE (root->left->right) ||
5710 !IS_AST_LIT_VALUE (root->right->right))
5713 /* make sure it is the same symbol */
5714 if (!isAstEqual (root->left->left,
5718 if (AST_ULONG_VALUE (root->left->right) != 1)
5721 if (AST_ULONG_VALUE (root->right->right) !=
5722 (getSize (TTYPE (root->left->left)) * 8 - 1))
5725 /* make sure the port supports RRC */
5726 if (port->hasExtBitOp
5727 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5730 /* whew got the first case : create the AST */
5731 return newNode (RRC, root->left->left, NULL);
5735 /* fourth and last case for now */
5736 /* (?symbol << 7) | (?symbol >> 1) */
5737 if (IS_RIGHT_OP (root->right) &&
5738 IS_LEFT_OP (root->left))
5741 if (!SPEC_USIGN (TETYPE (root->left->left)))
5744 if (!IS_AST_LIT_VALUE (root->left->right) ||
5745 !IS_AST_LIT_VALUE (root->right->right))
5748 /* make sure it is the same symbol */
5749 if (!isAstEqual (root->left->left,
5753 if (AST_ULONG_VALUE (root->right->right) != 1)
5756 if (AST_ULONG_VALUE (root->left->right) !=
5757 (getSize (TTYPE (root->left->left)) * 8 - 1))
5760 /* make sure the port supports RRC */
5761 if (port->hasExtBitOp
5762 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5765 /* whew got the first case : create the AST */
5766 return newNode (RRC, root->left->left, NULL);
5770 /* not found return root */
5774 /*-----------------------------------------------------------------*/
5775 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5776 /*-----------------------------------------------------------------*/
5778 optimizeSWAP (ast * root)
5780 /* will look for trees of the form
5781 (?expr << 4) | (?expr >> 4) or
5782 (?expr >> 4) | (?expr << 4) will make that
5783 into a SWAP : operation ..
5784 note : by 4 I mean (number of bits required to hold the
5786 /* if the root operation is not a | operation then not */
5787 if (!IS_BITOR (root))
5790 /* (?expr << 4) | (?expr >> 4) */
5791 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5792 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5795 if (!SPEC_USIGN (TETYPE (root->left->left)))
5798 if (!IS_AST_LIT_VALUE (root->left->right) ||
5799 !IS_AST_LIT_VALUE (root->right->right))
5802 /* make sure it is the same expression */
5803 if (!isAstEqual (root->left->left,
5807 if (AST_ULONG_VALUE (root->left->right) !=
5808 (getSize (TTYPE (root->left->left)) * 4))
5811 if (AST_ULONG_VALUE (root->right->right) !=
5812 (getSize (TTYPE (root->left->left)) * 4))
5815 /* make sure the port supports SWAP */
5816 if (port->hasExtBitOp
5817 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5820 /* found it : create the AST */
5821 return newNode (SWAP, root->left->left, NULL);
5825 /* not found return root */
5829 /*-----------------------------------------------------------------*/
5830 /* optimizeCompare - optimizes compares for bit variables */
5831 /*-----------------------------------------------------------------*/
5833 optimizeCompare (ast * root)
5835 ast *optExpr = NULL;
5838 unsigned int litValue;
5840 /* if nothing then return nothing */
5844 /* if not a compare op then do leaves */
5845 if (!IS_COMPARE_OP (root))
5847 root->left = optimizeCompare (root->left);
5848 root->right = optimizeCompare (root->right);
5852 /* if left & right are the same then depending
5853 of the operation do */
5854 if (isAstEqual (root->left, root->right))
5856 switch (root->opval.op)
5861 optExpr = newAst_VALUE (constCharVal (0));
5866 optExpr = newAst_VALUE (constCharVal (1));
5870 return decorateType (optExpr, RESULT_TYPE_NONE);
5873 vleft = (root->left->type == EX_VALUE ?
5874 root->left->opval.val : NULL);
5876 vright = (root->right->type == EX_VALUE ?
5877 root->right->opval.val : NULL);
5879 /* if left is a BITVAR in BITSPACE */
5880 /* and right is a LITERAL then */
5881 /* optimize else do nothing */
5882 if (vleft && vright &&
5883 IS_BITVAR (vleft->etype) &&
5884 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5885 IS_LITERAL (vright->etype))
5888 /* if right side > 1 then comparison may never succeed */
5889 if ((litValue = (int) ulFromVal (vright)) > 1)
5891 werror (W_BAD_COMPARE);
5897 switch (root->opval.op)
5899 case '>': /* bit value greater than 1 cannot be */
5900 werror (W_BAD_COMPARE);
5904 case '<': /* bit value < 1 means 0 */
5906 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5909 case LE_OP: /* bit value <= 1 means no check */
5910 optExpr = newAst_VALUE (vright);
5913 case GE_OP: /* bit value >= 1 means only check for = */
5915 optExpr = newAst_VALUE (vleft);
5920 { /* literal is zero */
5921 switch (root->opval.op)
5923 case '<': /* bit value < 0 cannot be */
5924 werror (W_BAD_COMPARE);
5928 case '>': /* bit value > 0 means 1 */
5930 optExpr = newAst_VALUE (vleft);
5933 case LE_OP: /* bit value <= 0 means no check */
5934 case GE_OP: /* bit value >= 0 means no check */
5935 werror (W_BAD_COMPARE);
5939 case EQ_OP: /* bit == 0 means ! of bit */
5940 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5944 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5945 } /* end-of-if of BITVAR */
5951 /*-----------------------------------------------------------------*/
5952 /* addSymToBlock : adds the symbol to the first block we find */
5953 /*-----------------------------------------------------------------*/
5955 addSymToBlock (symbol * sym, ast * tree)
5957 /* reached end of tree or a leaf */
5958 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5962 if (IS_AST_OP (tree) &&
5963 tree->opval.op == BLOCK)
5966 symbol *lsym = copySymbol (sym);
5968 lsym->next = AST_VALUES (tree, sym);
5969 AST_VALUES (tree, sym) = lsym;
5973 addSymToBlock (sym, tree->left);
5974 addSymToBlock (sym, tree->right);
5977 /*-----------------------------------------------------------------*/
5978 /* processRegParms - do processing for register parameters */
5979 /*-----------------------------------------------------------------*/
5981 processRegParms (value * args, ast * body)
5985 if (IS_REGPARM (args->etype))
5986 addSymToBlock (args->sym, body);
5991 /*-----------------------------------------------------------------*/
5992 /* resetParmKey - resets the operandkeys for the symbols */
5993 /*-----------------------------------------------------------------*/
5994 DEFSETFUNC (resetParmKey)
6005 /*------------------------------------------------------------------*/
6006 /* fixupInlineLabel - change a label in an inlined function so that */
6007 /* it is always unique no matter how many times */
6008 /* the function is inlined. */
6009 /*------------------------------------------------------------------*/
6011 fixupInlineLabel (symbol * sym)
6013 char name[SDCC_NAME_MAX + 1];
6015 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
6016 strcpy (sym->name, name);
6019 /*------------------------------------------------------------------*/
6020 /* copyAstLoc - copy location information (file, line, block, etc.) */
6021 /* from one ast node to another */
6022 /*------------------------------------------------------------------*/
6024 copyAstLoc (ast * dest, ast * src)
6026 dest->filename = src->filename;
6027 dest->lineno = src->lineno;
6028 dest->level = src->level;
6029 dest->block = src->block;
6030 dest->seqPoint = src->seqPoint;
6033 /*-----------------------------------------------------------------*/
6034 /* fixupInline - perform various fixups on an inline function tree */
6035 /* to take into account that it is no longer a */
6036 /* stand-alone function. */
6037 /*-----------------------------------------------------------------*/
6039 fixupInline (ast * tree, int level)
6041 int savedBlockno = currBlockno;
6043 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6047 currBlockno = ++blockNo;
6050 /* Add any declared variables back into the symbol table */
6051 decls = tree->values.sym;
6054 decls->level = level;
6055 decls->block = currBlockno;
6056 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6057 decls = decls->next;
6061 tree->level = level;
6062 tree->block = currBlockno;
6064 /* Update symbols */
6065 if (IS_AST_VALUE (tree) &&
6066 tree->opval.val->sym)
6068 symbol * sym = tree->opval.val->sym;
6071 sym->block = currBlockno;
6074 SYM_SPIL_LOC (sym) = NULL;
6077 /* If the symbol is a label, we need to renumber it */
6079 fixupInlineLabel (sym);
6082 /* Update IFX target labels */
6083 if (tree->type == EX_OP && tree->opval.op == IFX)
6085 if (tree->trueLabel)
6086 fixupInlineLabel (tree->trueLabel);
6087 if (tree->falseLabel)
6088 fixupInlineLabel (tree->falseLabel);
6091 /* Replace RETURN with optional assignment and a GOTO to the end */
6092 /* of the inlined function */
6093 if (tree->type == EX_OP && tree->opval.op == RETURN)
6095 ast * assignTree = NULL;
6098 if (inlineState.retsym && tree->right)
6100 assignTree = newNode ('=',
6101 newAst_VALUE (symbolVal (inlineState.retsym)),
6103 copyAstLoc (assignTree, tree);
6106 gotoTree = newNode (GOTO,
6107 newAst_VALUE (symbolVal (inlineState.retlab)),
6109 copyAstLoc (gotoTree, tree);
6111 tree->opval.op = NULLOP;
6112 tree->left = assignTree;
6113 tree->right = gotoTree;
6116 /* Update any children */
6118 fixupInline (tree->left, level);
6120 fixupInline (tree->right, level);
6122 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6124 symbol * label = tree->left->opval.val->sym;
6126 label->key = labelKey++;
6127 /* Add this label back into the symbol table */
6128 addSym (LabelTab, label, label->name, label->level, 0, 0);
6131 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6134 currBlockno = savedBlockno;
6138 /*-----------------------------------------------------------------*/
6139 /* inlineAddDecl - add a variable declaration to an ast block. It */
6140 /* is also added to the symbol table if addSymTab */
6142 /*-----------------------------------------------------------------*/
6144 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6147 SYM_SPIL_LOC (sym) = NULL;
6151 symbol **decl = &(block->values.sym);
6153 sym->level = block->level;
6154 sym->block = block->block;
6158 if (strcmp ((*decl)->name, sym->name) == 0)
6160 decl = &( (*decl)->next );
6166 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6171 /*-----------------------------------------------------------------*/
6172 /* inlineTempVar - create a temporary variable for inlining */
6173 /*-----------------------------------------------------------------*/
6175 inlineTempVar (sym_link * type, int level)
6179 sym = newSymbol (genSymName(level), level );
6180 sym->type = copyLinkChain (type);
6181 sym->etype = getSpec(sym->type);
6182 SPEC_SCLS (sym->etype) = S_AUTO;
6183 SPEC_OCLS (sym->etype) = NULL;
6184 SPEC_EXTR (sym->etype) = 0;
6185 SPEC_STAT (sym->etype) = 0;
6186 if IS_SPEC (sym->type)
6187 SPEC_VOLATILE (sym->type) = 0;
6189 DCL_PTR_VOLATILE (sym->type) = 0;
6190 SPEC_ABSA (sym->etype) = 0;
6195 /*-----------------------------------------------------------------*/
6196 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6197 /*-----------------------------------------------------------------*/
6199 inlineFindParmRecurse (ast * parms, int *index)
6204 if (parms->type == EX_OP && parms->opval.op == PARAM)
6208 p=inlineFindParmRecurse (parms->left, index);
6211 p=inlineFindParmRecurse (parms->right, index);
6221 /*-----------------------------------------------------------------*/
6222 /* inlineFindParm - search an ast tree of parameters to find one */
6223 /* at a particular index (0=first parameter). */
6224 /* Returns NULL if not found. */
6225 /*-----------------------------------------------------------------*/
6227 inlineFindParm (ast * parms, int index)
6229 return inlineFindParmRecurse (parms, &index);
6232 /*-----------------------------------------------------------------*/
6233 /* expandInlineFuncs - replace calls to inline functions with the */
6234 /* function itself */
6235 /*-----------------------------------------------------------------*/
6237 expandInlineFuncs (ast * tree, ast * block)
6239 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6240 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6242 symbol * func = tree->left->opval.val->sym;
6245 /* The symbol is probably not bound yet, so find the real one */
6246 csym = findSymWithLevel (SymbolTab, func);
6250 /* Is this an inline function that we can inline? */
6251 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6253 symbol * retsym = NULL;
6261 /* Generate a label for the inlined function to branch to */
6262 /* in case it contains a return statement */
6263 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6266 inlineState.retlab = retlab;
6268 /* Build the subtree for the inlined function in the form: */
6269 /* { //inlinetree block */
6270 /* { //inlinetree2 block */
6271 /* inline_function_code; */
6275 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6276 copyAstLoc (temptree, tree);
6277 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6278 copyAstLoc (temptree, tree);
6279 temptree = newNode (BLOCK, NULL, temptree);
6280 copyAstLoc (temptree, tree);
6281 inlinetree2 = temptree;
6282 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6283 copyAstLoc (inlinetree, tree);
6285 /* To pass parameters to the inlined function, we need some */
6286 /* intermediate variables. This avoids scoping problems */
6287 /* when the parameter declaration names are used differently */
6288 /* during the function call. For example, a function */
6289 /* declared as func(int x, int y) but called as func(y,x). */
6290 /* { //inlinetree block */
6291 /* type1 temparg1 = argument1; */
6293 /* typen tempargn = argumentn; */
6294 /* { //inlinetree2 block */
6295 /* type1 param1 = temparg1; */
6297 /* typen paramn = tempargn; */
6298 /* inline_function_code; */
6302 args = FUNC_ARGS (func->type);
6309 ast * passedarg = inlineFindParm (tree->right, argIndex);
6313 werror(E_TOO_FEW_PARMS);
6317 temparg = inlineTempVar (args->sym->type, tree->level+1);
6318 inlineAddDecl (temparg, inlinetree, FALSE);
6320 assigntree = newNode ('=',
6321 newAst_VALUE (symbolVal (temparg)),
6323 assigntree->initMode=1; // tell that assignment is initializer
6324 inlinetree->right = newNode (NULLOP,
6328 parm = copySymbol (args->sym);
6329 inlineAddDecl (parm, inlinetree2, FALSE);
6332 assigntree = newNode ('=',
6333 newAst_VALUE (symbolVal (parm)),
6334 newAst_VALUE (symbolVal (temparg)));
6335 assigntree->initMode=1; // tell that assignment is initializer
6336 inlinetree2->right = newNode (NULLOP,
6338 inlinetree2->right);
6344 /* Handle the return type */
6345 if (!IS_VOID (func->type->next))
6347 /* Create a temporary symbol to hold the return value and */
6348 /* join it with the inlined function using the comma */
6349 /* operator. The fixupInline function will take care of */
6350 /* changing return statements into assignments to retsym. */
6351 /* (parameter passing and return label omitted for clarity) */
6352 /* rettype retsym; */
6354 /* {{inline_function_code}}, retsym */
6356 retsym = inlineTempVar (func->type->next, tree->level);
6357 inlineAddDecl (retsym, block, TRUE);
6359 tree->opval.op = ',';
6360 tree->left = inlinetree;
6361 tree->right = newAst_VALUE (symbolVal (retsym));
6365 tree->opval.op = NULLOP;
6367 tree->right = inlinetree;
6369 inlineState.retsym = retsym;
6371 /* Renumber the various internal counters on the inlined */
6372 /* function's tree nodes and symbols. Add the inlined */
6373 /* function's local variables to the appropriate scope(s). */
6374 /* Convert inlined return statements to an assignment to */
6375 /* retsym (if needed) and a goto retlab. */
6376 fixupInline (inlinetree, inlinetree->level);
6377 inlineState.count++;
6381 /* Recursively continue to search for functions to inline. */
6382 if (IS_AST_OP (tree))
6384 if (tree->opval.op == BLOCK)
6388 expandInlineFuncs (tree->left, block);
6390 expandInlineFuncs (tree->right, block);
6394 /*-----------------------------------------------------------------*/
6395 /* createFunction - This is the key node that calls the iCode for */
6396 /* generating the code for a function. Note code */
6397 /* is generated function by function, later when */
6398 /* add inter-procedural analysis this will change */
6399 /*-----------------------------------------------------------------*/
6401 createFunction (symbol * name, ast * body)
6407 iCode *piCode = NULL;
6409 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6410 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6412 /* if check function return 0 then some problem */
6413 if (checkFunction (name, NULL) == 0)
6416 /* create a dummy block if none exists */
6418 body = newNode (BLOCK, NULL, NULL);
6422 /* check if the function name already in the symbol table */
6423 if ((csym = findSym (SymbolTab, NULL, name->name)))
6426 /* special case for compiler defined functions
6427 we need to add the name to the publics list : this
6428 actually means we are now compiling the compiler
6432 addSet (&publics, name);
6437 addSymChain (&name);
6438 allocVariables (name);
6440 name->lastLine = lexLineno;
6443 /* set the stack pointer */
6444 stackPtr = -port->stack.direction * port->stack.call_overhead;
6447 if (IFFUNC_ISISR (name->type))
6448 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6450 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6452 if (options.useXstack)
6453 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6455 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6458 fetype = getSpec (name->type); /* get the specifier for the function */
6459 /* if this is a reentrant function then */
6460 if (IFFUNC_ISREENT (name->type))
6463 inlineState.count = 0;
6464 expandInlineFuncs (body, NULL);
6466 if (FUNC_ISINLINE (name->type))
6467 name->funcTree = copyAst (body);
6469 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6471 /* do processing for parameters that are passed in registers */
6472 processRegParms (FUNC_ARGS(name->type), body);
6474 /* set the stack pointer */
6478 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6480 /* allocate & autoinit the block variables */
6481 processBlockVars (body, &stack, ALLOCATE);
6483 /* name needs to be mangled */
6484 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6486 body = resolveSymbols (body); /* resolve the symbols */
6487 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6489 /* save the stack information */
6490 if (options.useXstack)
6491 name->xstack = SPEC_STAK (fetype) = stack;
6493 name->stack = SPEC_STAK (fetype) = stack;
6495 ex = newAst_VALUE (symbolVal (name)); /* create name */
6496 ex = newNode (FUNCTION, ex, body);
6497 ex->values.args = FUNC_ARGS(name->type);
6499 if (options.dump_tree)
6504 /* Do not generate code for inline functions unless extern also. */
6506 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6509 /* Temporary hack: always generate code for static inline functions. */
6510 /* Ideally static inline functions should only be generated if needed. */
6511 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6515 /* create the node & generate intermediate code */
6517 codeOutBuf = &code->oBuf;
6518 piCode = iCodeFromAst (ex);
6519 name->generated = 1;
6524 eBBlockFromiCode (piCode);
6526 /* if there are any statics then do them */
6529 GcurMemmap = statsg;
6530 codeOutBuf = &statsg->oBuf;
6531 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6537 /* dealloc the block variables */
6538 processBlockVars (body, &stack, DEALLOCATE);
6539 outputDebugStackSymbols();
6540 /* deallocate paramaters */
6541 deallocParms (FUNC_ARGS(name->type));
6543 if (IFFUNC_ISREENT (name->type))
6546 /* we are done freeup memory & cleanup */
6548 if (port->reset_labelKey)
6551 FUNC_HASBODY(name->type) = 1;
6552 addSet (&operKeyReset, name);
6553 applyToSet (operKeyReset, resetParmKey);
6558 cleanUpLevel (LabelTab, 0);
6559 cleanUpBlock (StructTab, 1);
6560 cleanUpBlock (TypedefTab, 1);
6562 xstack->syms = NULL;
6563 istack->syms = NULL;
6568 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6569 /*-----------------------------------------------------------------*/
6570 /* ast_print : prints the ast (for debugging purposes) */
6571 /*-----------------------------------------------------------------*/
6573 void ast_print (ast * tree, FILE *outfile, int indent)
6578 /* can print only decorated trees */
6579 if (!tree->decorated) return;
6581 /* if any child is an error | this one is an error do nothing */
6582 if (tree->isError ||
6583 (tree->left && tree->left->isError) ||
6584 (tree->right && tree->right->isError)) {
6585 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6589 /* print the line */
6590 /* if not block & function */
6591 if (tree->type == EX_OP &&
6592 (tree->opval.op != FUNCTION &&
6593 tree->opval.op != BLOCK &&
6594 tree->opval.op != NULLOP)) {
6597 if (tree->opval.op == FUNCTION) {
6599 value *args=FUNC_ARGS(tree->left->opval.val->type);
6600 fprintf(outfile,"FUNCTION (%s=%p) type (",
6601 tree->left->opval.val->name, tree);
6602 printTypeChain (tree->left->opval.val->type->next,outfile);
6603 fprintf(outfile,") args (");
6606 fprintf (outfile, ", ");
6608 printTypeChain (args ? args->type : NULL, outfile);
6610 args= args ? args->next : NULL;
6612 fprintf(outfile,")\n");
6613 ast_print(tree->left,outfile,indent);
6614 ast_print(tree->right,outfile,indent);
6617 if (tree->opval.op == BLOCK) {
6618 symbol *decls = tree->values.sym;
6619 INDENT(indent,outfile);
6620 fprintf(outfile,"{\n");
6622 INDENT(indent+2,outfile);
6623 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6624 decls->name, decls);
6625 printTypeChain(decls->type,outfile);
6626 fprintf(outfile,")\n");
6628 decls = decls->next;
6630 ast_print(tree->right,outfile,indent+2);
6631 INDENT(indent,outfile);
6632 fprintf(outfile,"}\n");
6635 if (tree->opval.op == NULLOP) {
6636 ast_print(tree->left,outfile,indent);
6637 ast_print(tree->right,outfile,indent);
6640 INDENT(indent,outfile);
6642 /*------------------------------------------------------------------*/
6643 /*----------------------------*/
6644 /* leaf has been reached */
6645 /*----------------------------*/
6646 /* if this is of type value */
6647 /* just get the type */
6648 if (tree->type == EX_VALUE) {
6650 if (IS_LITERAL (tree->opval.val->etype)) {
6651 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6652 if (SPEC_USIGN (tree->opval.val->etype))
6653 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6655 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6656 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6657 floatFromVal(tree->opval.val));
6658 } else if (tree->opval.val->sym) {
6659 /* if the undefined flag is set then give error message */
6660 if (tree->opval.val->sym->undefined) {
6661 fprintf(outfile,"UNDEFINED SYMBOL ");
6663 fprintf(outfile,"SYMBOL ");
6665 fprintf(outfile,"(%s=%p @ %p)",
6666 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6669 fprintf(outfile," type (");
6670 printTypeChain(tree->ftype,outfile);
6671 fprintf(outfile,")\n");
6673 fprintf(outfile,"\n");
6678 /* if type link for the case of cast */
6679 if (tree->type == EX_LINK) {
6680 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6681 printTypeChain(tree->opval.lnk,outfile);
6682 fprintf(outfile,")\n");
6687 /* depending on type of operator do */
6689 switch (tree->opval.op) {
6690 /*------------------------------------------------------------------*/
6691 /*----------------------------*/
6693 /*----------------------------*/
6695 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6696 printTypeChain(tree->ftype,outfile);
6697 fprintf(outfile,")\n");
6698 ast_print(tree->left,outfile,indent+2);
6699 ast_print(tree->right,outfile,indent+2);
6702 /*------------------------------------------------------------------*/
6703 /*----------------------------*/
6705 /*----------------------------*/
6707 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6708 printTypeChain(tree->ftype,outfile);
6709 fprintf(outfile,")\n");
6710 ast_print(tree->left,outfile,indent+2);
6711 ast_print(tree->right,outfile,indent+2);
6714 /*------------------------------------------------------------------*/
6715 /*----------------------------*/
6716 /* struct/union pointer */
6717 /*----------------------------*/
6719 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6720 printTypeChain(tree->ftype,outfile);
6721 fprintf(outfile,")\n");
6722 ast_print(tree->left,outfile,indent+2);
6723 ast_print(tree->right,outfile,indent+2);
6726 /*------------------------------------------------------------------*/
6727 /*----------------------------*/
6728 /* ++/-- operation */
6729 /*----------------------------*/
6732 fprintf(outfile,"post-");
6734 fprintf(outfile,"pre-");
6735 fprintf(outfile,"INC_OP (%p) type (",tree);
6736 printTypeChain(tree->ftype,outfile);
6737 fprintf(outfile,")\n");
6738 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6739 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6744 fprintf(outfile,"post-");
6746 fprintf(outfile,"pre-");
6747 fprintf(outfile,"DEC_OP (%p) type (",tree);
6748 printTypeChain(tree->ftype,outfile);
6749 fprintf(outfile,")\n");
6750 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6751 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6754 /*------------------------------------------------------------------*/
6755 /*----------------------------*/
6757 /*----------------------------*/
6760 fprintf(outfile,"& (%p) type (",tree);
6761 printTypeChain(tree->ftype,outfile);
6762 fprintf(outfile,")\n");
6763 ast_print(tree->left,outfile,indent+2);
6764 ast_print(tree->right,outfile,indent+2);
6766 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6767 printTypeChain(tree->ftype,outfile);
6768 fprintf(outfile,")\n");
6769 ast_print(tree->left,outfile,indent+2);
6770 ast_print(tree->right,outfile,indent+2);
6773 /*----------------------------*/
6775 /*----------------------------*/
6777 fprintf(outfile,"OR (%p) type (",tree);
6778 printTypeChain(tree->ftype,outfile);
6779 fprintf(outfile,")\n");
6780 ast_print(tree->left,outfile,indent+2);
6781 ast_print(tree->right,outfile,indent+2);
6783 /*------------------------------------------------------------------*/
6784 /*----------------------------*/
6786 /*----------------------------*/
6788 fprintf(outfile,"XOR (%p) type (",tree);
6789 printTypeChain(tree->ftype,outfile);
6790 fprintf(outfile,")\n");
6791 ast_print(tree->left,outfile,indent+2);
6792 ast_print(tree->right,outfile,indent+2);
6795 /*------------------------------------------------------------------*/
6796 /*----------------------------*/
6798 /*----------------------------*/
6800 fprintf(outfile,"DIV (%p) type (",tree);
6801 printTypeChain(tree->ftype,outfile);
6802 fprintf(outfile,")\n");
6803 ast_print(tree->left,outfile,indent+2);
6804 ast_print(tree->right,outfile,indent+2);
6806 /*------------------------------------------------------------------*/
6807 /*----------------------------*/
6809 /*----------------------------*/
6811 fprintf(outfile,"MOD (%p) type (",tree);
6812 printTypeChain(tree->ftype,outfile);
6813 fprintf(outfile,")\n");
6814 ast_print(tree->left,outfile,indent+2);
6815 ast_print(tree->right,outfile,indent+2);
6818 /*------------------------------------------------------------------*/
6819 /*----------------------------*/
6820 /* address dereference */
6821 /*----------------------------*/
6822 case '*': /* can be unary : if right is null then unary operation */
6824 fprintf(outfile,"DEREF (%p) type (",tree);
6825 printTypeChain(tree->ftype,outfile);
6826 fprintf(outfile,")\n");
6827 ast_print(tree->left,outfile,indent+2);
6830 /*------------------------------------------------------------------*/
6831 /*----------------------------*/
6832 /* multiplication */
6833 /*----------------------------*/
6834 fprintf(outfile,"MULT (%p) type (",tree);
6835 printTypeChain(tree->ftype,outfile);
6836 fprintf(outfile,")\n");
6837 ast_print(tree->left,outfile,indent+2);
6838 ast_print(tree->right,outfile,indent+2);
6842 /*------------------------------------------------------------------*/
6843 /*----------------------------*/
6844 /* unary '+' operator */
6845 /*----------------------------*/
6849 fprintf(outfile,"UPLUS (%p) type (",tree);
6850 printTypeChain(tree->ftype,outfile);
6851 fprintf(outfile,")\n");
6852 ast_print(tree->left,outfile,indent+2);
6854 /*------------------------------------------------------------------*/
6855 /*----------------------------*/
6857 /*----------------------------*/
6858 fprintf(outfile,"ADD (%p) type (",tree);
6859 printTypeChain(tree->ftype,outfile);
6860 fprintf(outfile,")\n");
6861 ast_print(tree->left,outfile,indent+2);
6862 ast_print(tree->right,outfile,indent+2);
6865 /*------------------------------------------------------------------*/
6866 /*----------------------------*/
6868 /*----------------------------*/
6869 case '-': /* can be unary */
6871 fprintf(outfile,"UMINUS (%p) type (",tree);
6872 printTypeChain(tree->ftype,outfile);
6873 fprintf(outfile,")\n");
6874 ast_print(tree->left,outfile,indent+2);
6876 /*------------------------------------------------------------------*/
6877 /*----------------------------*/
6879 /*----------------------------*/
6880 fprintf(outfile,"SUB (%p) type (",tree);
6881 printTypeChain(tree->ftype,outfile);
6882 fprintf(outfile,")\n");
6883 ast_print(tree->left,outfile,indent+2);
6884 ast_print(tree->right,outfile,indent+2);
6887 /*------------------------------------------------------------------*/
6888 /*----------------------------*/
6890 /*----------------------------*/
6892 fprintf(outfile,"COMPL (%p) type (",tree);
6893 printTypeChain(tree->ftype,outfile);
6894 fprintf(outfile,")\n");
6895 ast_print(tree->left,outfile,indent+2);
6897 /*------------------------------------------------------------------*/
6898 /*----------------------------*/
6900 /*----------------------------*/
6902 fprintf(outfile,"NOT (%p) type (",tree);
6903 printTypeChain(tree->ftype,outfile);
6904 fprintf(outfile,")\n");
6905 ast_print(tree->left,outfile,indent+2);
6907 /*------------------------------------------------------------------*/
6908 /*----------------------------*/
6910 /*----------------------------*/
6912 fprintf(outfile,"RRC (%p) type (",tree);
6913 printTypeChain(tree->ftype,outfile);
6914 fprintf(outfile,")\n");
6915 ast_print(tree->left,outfile,indent+2);
6919 fprintf(outfile,"RLC (%p) type (",tree);
6920 printTypeChain(tree->ftype,outfile);
6921 fprintf(outfile,")\n");
6922 ast_print(tree->left,outfile,indent+2);
6925 fprintf(outfile,"SWAP (%p) type (",tree);
6926 printTypeChain(tree->ftype,outfile);
6927 fprintf(outfile,")\n");
6928 ast_print(tree->left,outfile,indent+2);
6931 fprintf(outfile,"GETHBIT (%p) type (",tree);
6932 printTypeChain(tree->ftype,outfile);
6933 fprintf(outfile,")\n");
6934 ast_print(tree->left,outfile,indent+2);
6937 fprintf(outfile,"GETABIT (%p) type (",tree);
6938 printTypeChain(tree->ftype,outfile);
6939 fprintf(outfile,")\n");
6940 ast_print(tree->left,outfile,indent+2);
6941 ast_print(tree->right,outfile,indent+2);
6944 fprintf(outfile,"GETBYTE (%p) type (",tree);
6945 printTypeChain(tree->ftype,outfile);
6946 fprintf(outfile,")\n");
6947 ast_print(tree->left,outfile,indent+2);
6948 ast_print(tree->right,outfile,indent+2);
6951 fprintf(outfile,"GETWORD (%p) type (",tree);
6952 printTypeChain(tree->ftype,outfile);
6953 fprintf(outfile,")\n");
6954 ast_print(tree->left,outfile,indent+2);
6955 ast_print(tree->right,outfile,indent+2);
6958 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6959 printTypeChain(tree->ftype,outfile);
6960 fprintf(outfile,")\n");
6961 ast_print(tree->left,outfile,indent+2);
6962 ast_print(tree->right,outfile,indent+2);
6965 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6966 printTypeChain(tree->ftype,outfile);
6967 fprintf(outfile,")\n");
6968 ast_print(tree->left,outfile,indent+2);
6969 ast_print(tree->right,outfile,indent+2);
6971 /*------------------------------------------------------------------*/
6972 /*----------------------------*/
6974 /*----------------------------*/
6975 case CAST: /* change the type */
6976 fprintf(outfile,"CAST (%p) from type (",tree);
6977 printTypeChain(tree->right->ftype,outfile);
6978 fprintf(outfile,") to type (");
6979 printTypeChain(tree->ftype,outfile);
6980 fprintf(outfile,")\n");
6981 ast_print(tree->right,outfile,indent+2);
6985 fprintf(outfile,"ANDAND (%p) type (",tree);
6986 printTypeChain(tree->ftype,outfile);
6987 fprintf(outfile,")\n");
6988 ast_print(tree->left,outfile,indent+2);
6989 ast_print(tree->right,outfile,indent+2);
6992 fprintf(outfile,"OROR (%p) type (",tree);
6993 printTypeChain(tree->ftype,outfile);
6994 fprintf(outfile,")\n");
6995 ast_print(tree->left,outfile,indent+2);
6996 ast_print(tree->right,outfile,indent+2);
6999 /*------------------------------------------------------------------*/
7000 /*----------------------------*/
7001 /* comparison operators */
7002 /*----------------------------*/
7004 fprintf(outfile,"GT(>) (%p) type (",tree);
7005 printTypeChain(tree->ftype,outfile);
7006 fprintf(outfile,")\n");
7007 ast_print(tree->left,outfile,indent+2);
7008 ast_print(tree->right,outfile,indent+2);
7011 fprintf(outfile,"LT(<) (%p) type (",tree);
7012 printTypeChain(tree->ftype,outfile);
7013 fprintf(outfile,")\n");
7014 ast_print(tree->left,outfile,indent+2);
7015 ast_print(tree->right,outfile,indent+2);
7018 fprintf(outfile,"LE(<=) (%p) type (",tree);
7019 printTypeChain(tree->ftype,outfile);
7020 fprintf(outfile,")\n");
7021 ast_print(tree->left,outfile,indent+2);
7022 ast_print(tree->right,outfile,indent+2);
7025 fprintf(outfile,"GE(>=) (%p) type (",tree);
7026 printTypeChain(tree->ftype,outfile);
7027 fprintf(outfile,")\n");
7028 ast_print(tree->left,outfile,indent+2);
7029 ast_print(tree->right,outfile,indent+2);
7032 fprintf(outfile,"EQ(==) (%p) type (",tree);
7033 printTypeChain(tree->ftype,outfile);
7034 fprintf(outfile,")\n");
7035 ast_print(tree->left,outfile,indent+2);
7036 ast_print(tree->right,outfile,indent+2);
7039 fprintf(outfile,"NE(!=) (%p) type (",tree);
7040 printTypeChain(tree->ftype,outfile);
7041 fprintf(outfile,")\n");
7042 ast_print(tree->left,outfile,indent+2);
7043 ast_print(tree->right,outfile,indent+2);
7044 /*------------------------------------------------------------------*/
7045 /*----------------------------*/
7047 /*----------------------------*/
7048 case SIZEOF: /* evaluate wihout code generation */
7049 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7052 /*------------------------------------------------------------------*/
7053 /*----------------------------*/
7054 /* conditional operator '?' */
7055 /*----------------------------*/
7057 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7058 printTypeChain(tree->ftype,outfile);
7059 fprintf(outfile,")\n");
7060 ast_print(tree->left,outfile,indent+2);
7061 ast_print(tree->right,outfile,indent+2);
7065 fprintf(outfile,"COLON(:) (%p) type (",tree);
7066 printTypeChain(tree->ftype,outfile);
7067 fprintf(outfile,")\n");
7068 ast_print(tree->left,outfile,indent+2);
7069 ast_print(tree->right,outfile,indent+2);
7072 /*------------------------------------------------------------------*/
7073 /*----------------------------*/
7074 /* assignment operators */
7075 /*----------------------------*/
7077 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7078 printTypeChain(tree->ftype,outfile);
7079 fprintf(outfile,")\n");
7080 ast_print(tree->left,outfile,indent+2);
7081 ast_print(tree->right,outfile,indent+2);
7084 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7085 printTypeChain(tree->ftype,outfile);
7086 fprintf(outfile,")\n");
7087 ast_print(tree->left,outfile,indent+2);
7088 ast_print(tree->right,outfile,indent+2);
7091 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7092 printTypeChain(tree->ftype,outfile);
7093 fprintf(outfile,")\n");
7094 ast_print(tree->left,outfile,indent+2);
7095 ast_print(tree->right,outfile,indent+2);
7098 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7099 printTypeChain(tree->ftype,outfile);
7100 fprintf(outfile,")\n");
7101 ast_print(tree->left,outfile,indent+2);
7102 ast_print(tree->right,outfile,indent+2);
7105 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7106 printTypeChain(tree->ftype,outfile);
7107 fprintf(outfile,")\n");
7108 ast_print(tree->left,outfile,indent+2);
7109 ast_print(tree->right,outfile,indent+2);
7112 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7113 printTypeChain(tree->ftype,outfile);
7114 fprintf(outfile,")\n");
7115 ast_print(tree->left,outfile,indent+2);
7116 ast_print(tree->right,outfile,indent+2);
7119 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7120 printTypeChain(tree->ftype,outfile);
7121 fprintf(outfile,")\n");
7122 ast_print(tree->left,outfile,indent+2);
7123 ast_print(tree->right,outfile,indent+2);
7125 /*------------------------------------------------------------------*/
7126 /*----------------------------*/
7128 /*----------------------------*/
7130 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7131 printTypeChain(tree->ftype,outfile);
7132 fprintf(outfile,")\n");
7133 ast_print(tree->left,outfile,indent+2);
7134 ast_print(tree->right,outfile,indent+2);
7136 /*------------------------------------------------------------------*/
7137 /*----------------------------*/
7139 /*----------------------------*/
7141 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7142 printTypeChain(tree->ftype,outfile);
7143 fprintf(outfile,")\n");
7144 ast_print(tree->left,outfile,indent+2);
7145 ast_print(tree->right,outfile,indent+2);
7147 /*------------------------------------------------------------------*/
7148 /*----------------------------*/
7149 /* straight assignemnt */
7150 /*----------------------------*/
7152 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7153 printTypeChain(tree->ftype,outfile);
7154 fprintf(outfile,")\n");
7155 ast_print(tree->left,outfile,indent+2);
7156 ast_print(tree->right,outfile,indent+2);
7158 /*------------------------------------------------------------------*/
7159 /*----------------------------*/
7160 /* comma operator */
7161 /*----------------------------*/
7163 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7164 printTypeChain(tree->ftype,outfile);
7165 fprintf(outfile,")\n");
7166 ast_print(tree->left,outfile,indent+2);
7167 ast_print(tree->right,outfile,indent+2);
7169 /*------------------------------------------------------------------*/
7170 /*----------------------------*/
7172 /*----------------------------*/
7175 fprintf(outfile,"CALL (%p) type (",tree);
7176 printTypeChain(tree->ftype,outfile);
7177 fprintf(outfile,")\n");
7178 ast_print(tree->left,outfile,indent+2);
7179 ast_print(tree->right,outfile,indent+2);
7182 fprintf(outfile,"PARMS\n");
7183 ast_print(tree->left,outfile,indent+2);
7184 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7185 ast_print(tree->right,outfile,indent+2);
7188 /*------------------------------------------------------------------*/
7189 /*----------------------------*/
7190 /* return statement */
7191 /*----------------------------*/
7193 fprintf(outfile,"RETURN (%p) type (",tree);
7195 printTypeChain(tree->right->ftype,outfile);
7197 fprintf(outfile,")\n");
7198 ast_print(tree->right,outfile,indent+2);
7200 /*------------------------------------------------------------------*/
7201 /*----------------------------*/
7202 /* label statement */
7203 /*----------------------------*/
7205 fprintf(outfile,"LABEL (%p)\n",tree);
7206 ast_print(tree->left,outfile,indent+2);
7207 ast_print(tree->right,outfile,indent);
7209 /*------------------------------------------------------------------*/
7210 /*----------------------------*/
7211 /* switch statement */
7212 /*----------------------------*/
7216 fprintf(outfile,"SWITCH (%p) ",tree);
7217 ast_print(tree->left,outfile,0);
7218 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7219 INDENT(indent+2,outfile);
7220 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7221 (int) ulFromVal(val),
7222 tree->values.switchVals.swNum,
7223 (int) ulFromVal(val));
7225 ast_print(tree->right,outfile,indent);
7228 /*------------------------------------------------------------------*/
7229 /*----------------------------*/
7231 /*----------------------------*/
7233 fprintf(outfile,"IF (%p) \n",tree);
7234 ast_print(tree->left,outfile,indent+2);
7235 if (tree->trueLabel) {
7236 INDENT(indent+2,outfile);
7237 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7239 if (tree->falseLabel) {
7240 INDENT(indent+2,outfile);
7241 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7243 ast_print(tree->right,outfile,indent+2);
7245 /*----------------------------*/
7246 /* goto Statement */
7247 /*----------------------------*/
7249 fprintf(outfile,"GOTO (%p) \n",tree);
7250 ast_print(tree->left,outfile,indent+2);
7251 fprintf(outfile,"\n");
7253 /*------------------------------------------------------------------*/
7254 /*----------------------------*/
7256 /*----------------------------*/
7258 fprintf(outfile,"FOR (%p) \n",tree);
7259 if (AST_FOR( tree, initExpr)) {
7260 INDENT(indent+2,outfile);
7261 fprintf(outfile,"INIT EXPR ");
7262 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7264 if (AST_FOR( tree, condExpr)) {
7265 INDENT(indent+2,outfile);
7266 fprintf(outfile,"COND EXPR ");
7267 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7269 if (AST_FOR( tree, loopExpr)) {
7270 INDENT(indent+2,outfile);
7271 fprintf(outfile,"LOOP EXPR ");
7272 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7274 fprintf(outfile,"FOR LOOP BODY \n");
7275 ast_print(tree->left,outfile,indent+2);
7278 fprintf(outfile,"CRITICAL (%p) \n",tree);
7279 ast_print(tree->left,outfile,indent+2);
7287 ast_print(t,stdout,0);
7290 /*-----------------------------------------------------------------*/
7291 /* astErrors : returns non-zero if errors present in tree */
7292 /*-----------------------------------------------------------------*/
7293 int astErrors(ast *t)
7302 if (t->type == EX_VALUE
7303 && t->opval.val->sym
7304 && t->opval.val->sym->undefined)
7307 errors += astErrors(t->left);
7308 errors += astErrors(t->right);