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, IS_GENPTR (defParm->type) ? RESULT_TYPE_GPTR : 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)");
3876 /* if 'from' and 'to' are the same remove the superfluous cast,
3877 * this helps other optimizations */
3878 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3880 /* mark that the explicit cast has been removed,
3881 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3882 tree->right->values.removedCast = 1;
3886 /* If code memory is read only, then pointers to code memory */
3887 /* implicitly point to constants -- make this explicit */
3889 sym_link *t = LTYPE(tree);
3890 while (t && t->next)
3892 if (IS_CODEPTR(t) && port->mem.code_ro)
3894 if (IS_SPEC(t->next))
3895 SPEC_CONST (t->next) = 1;
3897 DCL_PTR_CONST (t->next) = 1;
3904 /* if the right is a literal replace the tree */
3905 if (IS_LITERAL (RETYPE (tree)))
3907 if (!IS_PTR (LTYPE (tree)))
3909 tree->type = EX_VALUE;
3911 valCastLiteral (LTYPE (tree),
3912 floatFromVal (valFromType (RETYPE (tree))));
3915 TTYPE (tree) = tree->opval.val->type;
3916 tree->values.literalFromCast = 1;
3918 else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3919 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */
3921 sym_link *rest = LTYPE(tree)->next;
3922 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3923 TTYPE(tree) = newLink(DECLARATOR);
3924 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3925 TTYPE(tree)->next = rest;
3926 tree->left->opval.lnk = TTYPE(tree);
3931 TTYPE (tree) = LTYPE (tree);
3937 TTYPE (tree) = LTYPE (tree);
3941 #if 0 // this is already checked, now this could be explicit
3942 /* if pointer to struct then check names */
3943 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3944 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3945 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3947 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3948 SPEC_STRUCT(LETYPE(tree))->tag);
3951 if (IS_ADDRESS_OF_OP(tree->right)
3952 && IS_AST_SYM_VALUE (tree->right->left)
3953 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype))
3955 symbol * sym = AST_SYMBOL (tree->right->left);
3956 unsigned int gptype = 0;
3957 unsigned int addr = SPEC_ADDR (sym->etype);
3959 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) || TARGET_IS_PIC16) )
3961 switch (SPEC_SCLS (sym->etype))
3964 gptype = GPTYPE_CODE;
3967 gptype = GPTYPE_FAR;
3971 gptype = GPTYPE_NEAR;
3974 gptype = GPTYPE_XSTACK;
3979 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3980 gptype = GPTYPE_NEAR;
3982 addr |= gptype << (8*(GPTRSIZE - 1));
3985 tree->type = EX_VALUE;
3986 tree->opval.val = valCastLiteral (LTYPE (tree), addr);
3987 TTYPE (tree) = tree->opval.val->type;
3988 TETYPE (tree) = getSpec (TTYPE (tree));
3991 tree->values.literalFromCast = 1;
3995 /* handle offsetof macro: */
3996 /* #define offsetof(TYPE, MEMBER) \ */
3997 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3998 if (IS_ADDRESS_OF_OP(tree->right)
3999 && IS_AST_OP (tree->right->left)
4000 && tree->right->left->opval.op == PTR_OP
4001 && IS_AST_OP (tree->right->left->left)
4002 && tree->right->left->left->opval.op == CAST
4003 && IS_AST_LIT_VALUE(tree->right->left->left->right))
4005 symbol *element = getStructElement (
4006 SPEC_STRUCT (LETYPE(tree->right->left)),
4007 AST_SYMBOL(tree->right->left->right)
4012 tree->type = EX_VALUE;
4013 tree->opval.val = valCastLiteral (
4016 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
4019 TTYPE (tree) = tree->opval.val->type;
4020 TETYPE (tree) = getSpec (TTYPE (tree));
4027 /* if the right is a literal replace the tree */
4028 if (IS_LITERAL (RETYPE (tree)))
4031 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) )
4033 /* rewrite (type *)litaddr
4035 and define type at litaddr temp
4036 (but only if type's storage class is not generic)
4038 ast *newTree = newNode ('&', NULL, NULL);
4041 TTYPE (newTree) = LTYPE (tree);
4042 TETYPE (newTree) = getSpec(LTYPE (tree));
4044 /* define a global symbol at the casted address*/
4045 sym = newSymbol(genSymName (0), 0);
4046 sym->type = LTYPE (tree)->next;
4048 sym->type = newLink (V_VOID);
4049 sym->etype = getSpec(sym->type);
4050 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4051 sym->lineDef = tree->lineno;
4054 SPEC_STAT (sym->etype) = 1;
4055 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4056 SPEC_ABSA(sym->etype) = 1;
4057 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4060 newTree->left = newAst_VALUE(symbolVal(sym));
4061 newTree->left->filename = tree->filename;
4062 newTree->left->lineno = tree->lineno;
4063 LTYPE (newTree) = sym->type;
4064 LETYPE (newTree) = sym->etype;
4065 LLVAL (newTree) = 1;
4066 LRVAL (newTree) = 0;
4067 TLVAL (newTree) = 1;
4071 if (!IS_PTR (LTYPE (tree)))
4073 tree->type = EX_VALUE;
4075 valCastLiteral (LTYPE (tree), floatFromVal (valFromType (RTYPE (tree))));
4076 TTYPE (tree) = tree->opval.val->type;
4079 tree->values.literalFromCast = 1;
4080 TETYPE (tree) = getSpec (TTYPE (tree));
4084 if (IS_GENPTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) && !IS_GENPTR (RTYPE (tree)) && (resultType != RESULT_TYPE_GPTR))
4086 DCL_TYPE (LTYPE (tree)) = DCL_TYPE (RTYPE (tree));
4088 TTYPE (tree) = LTYPE (tree);
4092 TETYPE (tree) = getSpec (TTYPE (tree));
4096 /*------------------------------------------------------------------*/
4097 /*----------------------------*/
4098 /* logical &&, || */
4099 /*----------------------------*/
4102 /* each must be arithmetic type or be a pointer */
4103 if (!IS_PTR (LTYPE (tree)) &&
4104 !IS_ARRAY (LTYPE (tree)) &&
4105 !IS_INTEGRAL (LTYPE (tree)))
4107 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4108 goto errorTreeReturn;
4111 if (!IS_PTR (RTYPE (tree)) &&
4112 !IS_ARRAY (RTYPE (tree)) &&
4113 !IS_INTEGRAL (RTYPE (tree)))
4115 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4116 goto errorTreeReturn;
4118 /* if they are both literal then */
4119 /* rewrite the tree */
4120 if (IS_LITERAL (RTYPE (tree)) &&
4121 IS_LITERAL (LTYPE (tree)))
4123 tree->type = EX_VALUE;
4124 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4125 valFromType (RTYPE (tree)),
4127 tree->right = tree->left = NULL;
4128 TETYPE (tree) = getSpec (TTYPE (tree) =
4129 tree->opval.val->type);
4132 LRVAL (tree) = RRVAL (tree) = 1;
4133 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4136 /*------------------------------------------------------------------*/
4137 /*----------------------------*/
4138 /* comparison operators */
4139 /*----------------------------*/
4147 ast *lt = optimizeCompare (tree);
4153 /* if they are pointers they must be castable */
4154 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4156 if (tree->opval.op==EQ_OP &&
4157 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4158 // we cannot cast a gptr to a !gptr: switch the leaves
4159 struct ast *s=tree->left;
4160 tree->left=tree->right;
4163 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4165 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4166 fprintf (stderr, "comparing type ");
4167 printTypeChain (LTYPE (tree), stderr);
4168 fprintf (stderr, "to type ");
4169 printTypeChain (RTYPE (tree), stderr);
4170 fprintf (stderr, "\n");
4171 goto errorTreeReturn;
4174 /* else they should be promotable to one another */
4177 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4178 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4180 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4182 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4183 fprintf (stderr, "comparing type ");
4184 printTypeChain (LTYPE (tree), stderr);
4185 fprintf (stderr, "to type ");
4186 printTypeChain (RTYPE (tree), stderr);
4187 fprintf (stderr, "\n");
4188 goto errorTreeReturn;
4193 CCR_RESULT ccr_result = CCR_OK;
4195 /* if left is integral and right is literal
4196 then check constant range */
4197 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4198 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4199 tree->opval.op, FALSE);
4200 if (ccr_result == CCR_OK &&
4201 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4202 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4203 tree->opval.op, TRUE);
4206 case CCR_ALWAYS_TRUE:
4207 case CCR_ALWAYS_FALSE:
4208 if (!options.lessPedantic)
4209 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4210 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4211 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4218 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4219 if (tree->opval.op == '>' &&
4220 SPEC_USIGN(LETYPE(tree)) &&
4221 IS_LITERAL(RTYPE(tree)) &&
4222 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4224 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4226 /* the parent is an ifx: */
4227 /* if (unsigned value) */
4231 /* (unsigned value) ? 1 : 0 */
4232 tree->opval.op = '?';
4233 tree->right = newNode (':',
4234 newAst_VALUE (constCharVal (1)),
4235 tree->right); /* val 0 */
4236 tree->right->filename = tree->filename;
4237 tree->right->lineno = tree->lineno;
4238 tree->right->left->filename = tree->filename;
4239 tree->right->left->lineno = tree->lineno;
4240 tree->decorated = 0;
4241 return decorateType (tree, resultType);
4244 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4245 if (IS_LITERAL(RTYPE(tree)) &&
4246 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4247 tree->opval.op == EQ_OP &&
4248 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4250 tree->opval.op = '!';
4252 tree->decorated = 0;
4253 return decorateType (tree, resultType);
4256 /* if they are both literal then */
4257 /* rewrite the tree */
4258 if (IS_LITERAL (RTYPE (tree)) &&
4259 IS_LITERAL (LTYPE (tree)))
4261 tree->type = EX_VALUE;
4262 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4263 valFromType (RETYPE (tree)),
4265 tree->right = tree->left = NULL;
4266 TETYPE (tree) = getSpec (TTYPE (tree) =
4267 tree->opval.val->type);
4271 /* if one is 'signed char ' and the other one is 'unsigned char' */
4272 /* it's necessary to promote to int */
4273 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4274 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4276 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4277 if it's possible to use a 'signed char' */
4279 /* is left a 'unsigned char'? */
4280 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4281 /* the value range of a 'unsigned char' is 0...255;
4282 if the actual value is < 128 it can be changed to signed */
4283 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4285 /* now we've got 2 'signed char'! */
4286 SPEC_USIGN (RETYPE (tree)) = 0;
4288 /* same test for the left operand: */
4289 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4290 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4292 SPEC_USIGN (LETYPE (tree)) = 0;
4296 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4297 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4298 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4302 LRVAL (tree) = RRVAL (tree) = 1;
4303 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4305 /* condition transformations */
4307 unsigned transformedOp = 0;
4309 switch (tree->opval.op)
4311 case '<': /* transform (a < b) to !(a >= b) */
4313 transformedOp = GE_OP;
4315 case '>': /* transform (a > b) to !(a <= b) */
4317 transformedOp = LE_OP;
4319 case LE_OP: /* transform (a <= b) to !(a > b) */
4321 transformedOp = '>';
4323 case GE_OP: /* transform (a >= b) to !(a < b) */
4325 transformedOp = '<';
4327 case NE_OP: /* transform (a != b) to !(a == b) */
4329 transformedOp = EQ_OP;
4331 case EQ_OP: /* transform (a == b) to !(a != b) */
4333 transformedOp = NE_OP;
4340 tree->opval.op = transformedOp;
4341 tree->decorated = 0;
4342 tree = newNode ('!', tree, NULL);
4343 tree->filename = tree->left->filename;
4344 tree->lineno = tree->left->lineno;
4345 return decorateType (tree, resultType);
4351 /*------------------------------------------------------------------*/
4352 /*----------------------------*/
4354 /*----------------------------*/
4355 case SIZEOF: /* evaluate wihout code generation */
4356 /* change the type to a integer */
4358 int size = getSize (tree->right->ftype);
4360 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4361 if (!size && !IS_VOID(tree->right->ftype))
4362 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4364 tree->type = EX_VALUE;
4365 tree->opval.val = constVal (buffer);
4366 tree->right = tree->left = NULL;
4367 TETYPE (tree) = getSpec (TTYPE (tree) =
4368 tree->opval.val->type);
4372 /*------------------------------------------------------------------*/
4373 /*----------------------------*/
4375 /*----------------------------*/
4377 /* return typeof enum value */
4378 tree->type = EX_VALUE;
4381 if (IS_SPEC(tree->right->ftype)) {
4382 switch (SPEC_NOUN(tree->right->ftype)) {
4384 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4385 else typeofv = TYPEOF_INT;
4388 typeofv = TYPEOF_FLOAT;
4391 typeofv = TYPEOF_FIXED16X16;
4394 typeofv = TYPEOF_CHAR;
4397 typeofv = TYPEOF_VOID;
4400 typeofv = TYPEOF_STRUCT;
4403 typeofv = TYPEOF_BITFIELD;
4406 typeofv = TYPEOF_BIT;
4409 typeofv = TYPEOF_SBIT;
4415 switch (DCL_TYPE(tree->right->ftype)) {
4417 typeofv = TYPEOF_POINTER;
4420 typeofv = TYPEOF_FPOINTER;
4423 typeofv = TYPEOF_CPOINTER;
4426 typeofv = TYPEOF_GPOINTER;
4429 typeofv = TYPEOF_PPOINTER;
4432 typeofv = TYPEOF_IPOINTER;
4435 typeofv = TYPEOF_ARRAY;
4438 typeofv = TYPEOF_FUNCTION;
4444 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4445 tree->opval.val = constVal (buffer);
4446 tree->right = tree->left = NULL;
4447 TETYPE (tree) = getSpec (TTYPE (tree) =
4448 tree->opval.val->type);
4451 /*------------------------------------------------------------------*/
4452 /*----------------------------*/
4453 /* conditional operator '?' */
4454 /*----------------------------*/
4456 /* the type is value of the colon operator (on the right) */
4457 assert (IS_COLON_OP (tree->right));
4459 /* If already known then replace the tree : optimizer will do it
4460 but faster to do it here. If done before decorating tree->right
4461 this can save generating unused const strings. */
4462 if (IS_LITERAL (LTYPE (tree)))
4464 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4465 return decorateType (tree->right->left, resultTypeProp);
4467 return decorateType (tree->right->right, resultTypeProp);
4470 tree->right = decorateType (tree->right, resultTypeProp);
4472 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4473 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4475 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4476 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4478 if ((valTrue != 0) && (valFalse == 0))
4480 /* assign cond to result */
4481 tree->left->decorated = 0;
4482 return decorateType (tree->left, resultTypeProp);
4484 else if ((valTrue == 0) && (valFalse != 0))
4486 /* assign !cond to result */
4487 tree->opval.op = '!';
4488 tree->decorated = 0;
4490 return decorateType (tree, resultTypeProp);
4494 /* they have the same boolean value, make them equal */
4495 tree->right->left = tree->right->right;
4499 /* if they are equal then replace the tree */
4500 if (isAstEqual (tree->right->left, tree->right->right))
4502 return tree->right->left;
4505 TTYPE (tree) = RTYPE (tree);
4506 TETYPE (tree) = getSpec (TTYPE (tree));
4510 /* if they don't match we have a problem */
4511 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4512 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4514 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4515 goto errorTreeReturn;
4518 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4519 resultType, tree->opval.op);
4520 TETYPE (tree) = getSpec (TTYPE (tree));
4524 #if 0 // assignment operators are converted by the parser
4525 /*------------------------------------------------------------------*/
4526 /*----------------------------*/
4527 /* assignment operators */
4528 /*----------------------------*/
4531 /* for these it must be both must be integral */
4532 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4533 !IS_ARITHMETIC (RTYPE (tree)))
4535 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4536 goto errorTreeReturn;
4539 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4541 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4542 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4546 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4547 goto errorTreeReturn;
4558 /* for these it must be both must be integral */
4559 if (!IS_INTEGRAL (LTYPE (tree)) ||
4560 !IS_INTEGRAL (RTYPE (tree)))
4562 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4563 goto errorTreeReturn;
4566 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4568 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4569 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4573 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4574 goto errorTreeReturn;
4580 /*------------------------------------------------------------------*/
4581 /*----------------------------*/
4583 /*----------------------------*/
4585 if (!(IS_PTR (LTYPE (tree)) ||
4586 IS_ARITHMETIC (LTYPE (tree))))
4588 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4589 goto errorTreeReturn;
4592 if (!(IS_PTR (RTYPE (tree)) ||
4593 IS_ARITHMETIC (RTYPE (tree))))
4595 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4596 goto errorTreeReturn;
4599 TETYPE (tree) = getSpec (TTYPE (tree) =
4600 computeType (LTYPE (tree),
4605 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4606 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4610 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4611 goto errorTreeReturn;
4617 /*------------------------------------------------------------------*/
4618 /*----------------------------*/
4620 /*----------------------------*/
4622 /* this is not a unary operation */
4623 /* if both pointers then problem */
4624 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4626 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4627 goto errorTreeReturn;
4630 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4632 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4633 goto errorTreeReturn;
4636 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4638 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4639 goto errorTreeReturn;
4642 TETYPE (tree) = getSpec (TTYPE (tree) =
4643 computeType (LTYPE (tree),
4648 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4649 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4653 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4654 goto errorTreeReturn;
4657 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4658 tree->opval.op = '=';
4663 /*------------------------------------------------------------------*/
4664 /*----------------------------*/
4665 /* straight assignemnt */
4666 /*----------------------------*/
4668 /* cannot be an aggregate */
4669 if (IS_AGGREGATE (LTYPE (tree)))
4671 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4672 goto errorTreeReturn;
4675 /* they should either match or be castable */
4676 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4678 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4679 printFromToType(RTYPE(tree),LTYPE(tree));
4682 /* if the left side of the tree is of type void
4683 then report error */
4684 if (IS_VOID (LTYPE (tree)))
4686 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4687 printFromToType(RTYPE(tree), LTYPE(tree));
4690 TETYPE (tree) = getSpec (TTYPE (tree) =
4694 if (!tree->initMode ) {
4695 if (IS_CONSTANT(LTYPE(tree)))
4696 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4700 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4701 goto errorTreeReturn;
4706 /*------------------------------------------------------------------*/
4707 /*----------------------------*/
4708 /* comma operator */
4709 /*----------------------------*/
4711 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4714 /*------------------------------------------------------------------*/
4715 /*----------------------------*/
4717 /*----------------------------*/
4720 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4721 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4723 if (tree->left->opval.op == '*' && !tree->left->right)
4724 tree->left = tree->left->left;
4727 /* require a function or pointer to function */
4728 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4730 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4731 goto errorTreeReturn;
4734 /* if there are parms, make sure that
4735 parms are decorate / process / reverse only once */
4737 !tree->right->decorated)
4742 if (IS_FUNCPTR (LTYPE (tree)))
4744 functype = LTYPE (tree)->next;
4745 processFuncPtrArgs (functype);
4748 functype = LTYPE (tree);
4750 if (processParms (tree->left, FUNC_ARGS(functype),
4751 &tree->right, &parmNumber, TRUE))
4753 goto errorTreeReturn;
4756 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4757 !IFFUNC_ISBUILTIN(functype))
4759 reverseParms (tree->right);
4762 TTYPE (tree) = functype->next;
4763 TETYPE (tree) = getSpec (TTYPE (tree));
4767 /*------------------------------------------------------------------*/
4768 /*----------------------------*/
4769 /* return statement */
4770 /*----------------------------*/
4775 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4777 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4778 printFromToType (RTYPE(tree), currFunc->type->next);
4779 goto errorTreeReturn;
4782 if (IS_VOID (currFunc->type->next)
4784 !IS_VOID (RTYPE (tree)))
4786 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4787 goto errorTreeReturn;
4790 /* if there is going to be a casting required then add it */
4791 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4794 decorateType (newNode (CAST,
4795 newAst_LINK (copyLinkChain (currFunc->type->next)),
4805 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4807 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4808 goto errorTreeReturn;
4811 TTYPE (tree) = TETYPE (tree) = NULL;
4814 /*------------------------------------------------------------------*/
4815 /*----------------------------*/
4816 /* switch statement */
4817 /*----------------------------*/
4819 /* the switch value must be an integer */
4820 if (!IS_INTEGRAL (LTYPE (tree)))
4822 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4823 goto errorTreeReturn;
4826 TTYPE (tree) = TETYPE (tree) = NULL;
4829 /*------------------------------------------------------------------*/
4830 /*----------------------------*/
4832 /*----------------------------*/
4834 tree->left = backPatchLabels (tree->left,
4837 TTYPE (tree) = TETYPE (tree) = NULL;
4840 /*------------------------------------------------------------------*/
4841 /*----------------------------*/
4843 /*----------------------------*/
4846 AST_FOR (tree, initExpr) = decorateType (
4847 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4848 AST_FOR (tree, condExpr) = decorateType (
4849 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4850 AST_FOR (tree, loopExpr) = decorateType (
4851 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4853 /* if the for loop is reversible then
4854 reverse it otherwise do what we normally
4860 if (isLoopReversible (tree, &sym, &init, &end))
4861 return reverseLoop (tree, sym, init, end);
4863 return decorateType (createFor (AST_FOR (tree, trueLabel),
4864 AST_FOR (tree, continueLabel),
4865 AST_FOR (tree, falseLabel),
4866 AST_FOR (tree, condLabel),
4867 AST_FOR (tree, initExpr),
4868 AST_FOR (tree, condExpr),
4869 AST_FOR (tree, loopExpr),
4870 tree->left), RESULT_TYPE_NONE);
4873 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4874 "node PARAM shouldn't be processed here");
4875 /* but in processParams() */
4878 TTYPE (tree) = TETYPE (tree) = NULL;
4882 /* some error found this tree will be killed */
4884 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4885 tree->opval.op = NULLOP;
4891 /*-----------------------------------------------------------------*/
4892 /* sizeofOp - processes size of operation */
4893 /*-----------------------------------------------------------------*/
4895 sizeofOp (sym_link * type)
4900 /* make sure the type is complete and sane */
4901 checkTypeSanity(type, "(sizeof)");
4903 /* get the size and convert it to character */
4904 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4905 if (!size && !IS_VOID(type))
4906 werror (E_SIZEOF_INCOMPLETE_TYPE);
4908 /* now convert into value */
4909 return constVal (buff);
4913 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4914 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4915 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4916 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4917 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4918 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4919 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4921 /*-----------------------------------------------------------------*/
4922 /* backPatchLabels - change and or not operators to flow control */
4923 /*-----------------------------------------------------------------*/
4925 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4931 /* while-loops insert a label between the IFX and the condition,
4932 therefore look behind the label too */
4933 if (tree->opval.op == LABEL &&
4935 IS_ANDORNOT (tree->right))
4937 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4941 if (!(IS_ANDORNOT (tree)))
4944 /* if this an and */
4947 static int localLbl = 0;
4950 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4951 localLabel = newSymbol (buffer, NestLevel);
4953 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4955 /* if left is already a IFX then just change the if true label in that */
4956 if (!IS_IFX (tree->left))
4957 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4959 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4960 /* right is a IFX then just join */
4961 if (IS_IFX (tree->right))
4962 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4964 tree->right = createLabel (localLabel, tree->right);
4965 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4967 return newNode (NULLOP, tree->left, tree->right);
4970 /* if this is an or operation */
4973 static int localLbl = 0;
4976 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4977 localLabel = newSymbol (buffer, NestLevel);
4979 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4981 /* if left is already a IFX then just change the if true label in that */
4982 if (!IS_IFX (tree->left))
4983 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4985 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4986 /* right is a IFX then just join */
4987 if (IS_IFX (tree->right))
4988 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4990 tree->right = createLabel (localLabel, tree->right);
4991 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4993 return newNode (NULLOP, tree->left, tree->right);
4999 /* call with exchanged labels */
5000 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
5002 /* if left isn't already a IFX */
5003 if (!IS_IFX (tree->left))
5005 tree->left = newNode (IFX, tree->left, NULL);
5006 tree->left->trueLabel = falseLabel;
5007 tree->left->falseLabel = trueLabel;
5014 tree->trueLabel = trueLabel;
5015 tree->falseLabel = falseLabel;
5022 /*-----------------------------------------------------------------*/
5023 /* createBlock - create expression tree for block */
5024 /*-----------------------------------------------------------------*/
5026 createBlock (symbol * decl, ast * body)
5030 /* if the block has nothing */
5034 ex = newNode (BLOCK, NULL, body);
5035 ex->values.sym = decl;
5038 ex->filename = NULL;
5043 /*-----------------------------------------------------------------*/
5044 /* createLabel - creates the expression tree for labels */
5045 /*-----------------------------------------------------------------*/
5047 createLabel (symbol * label, ast * stmnt)
5050 char name[SDCC_NAME_MAX + 1];
5053 /* must create fresh symbol if the symbol name */
5054 /* exists in the symbol table, since there can */
5055 /* be a variable with the same name as the labl */
5056 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5057 (csym->level == label->level))
5058 label = newSymbol (label->name, label->level);
5060 /* change the name before putting it in add _ */
5061 SNPRINTF(name, sizeof(name), "%s", label->name);
5063 /* put the label in the LabelSymbol table */
5064 /* but first check if a label of the same */
5066 if ((csym = findSym (LabelTab, NULL, name)))
5067 werror (E_DUPLICATE_LABEL, label->name);
5069 addSym (LabelTab, label, name, label->level, 0, 0);
5073 label->key = labelKey++;
5074 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5075 rValue->filename = NULL;
5081 /*-----------------------------------------------------------------*/
5082 /* createCase - generates the parsetree for a case statement */
5083 /*-----------------------------------------------------------------*/
5085 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5087 char caseLbl[SDCC_NAME_MAX + 1];
5091 /* if the switch statement does not exist */
5092 /* then case is out of context */
5095 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5099 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5100 /* if not a constant then error */
5101 if (!IS_LITERAL (caseVal->ftype))
5103 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5107 /* if not a integer than error */
5108 if (!IS_INTEGRAL (caseVal->ftype))
5110 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5114 /* find the end of the switch values chain */
5115 if (!(val = swStat->values.switchVals.swVals))
5116 swStat->values.switchVals.swVals = caseVal->opval.val;
5119 /* also order the cases according to value */
5121 int cVal = (int) ulFromVal (caseVal->opval.val);
5122 while (val && (int) ulFromVal (val) < cVal)
5128 /* if we reached the end then */
5131 pval->next = caseVal->opval.val;
5133 else if ((int) ulFromVal (val) == cVal)
5135 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5141 /* we found a value greater than */
5142 /* the current value we must add this */
5143 /* before the value */
5144 caseVal->opval.val->next = val;
5146 /* if this was the first in chain */
5147 if (swStat->values.switchVals.swVals == val)
5148 swStat->values.switchVals.swVals =
5151 pval->next = caseVal->opval.val;
5156 /* create the case label */
5157 SNPRINTF(caseLbl, sizeof(caseLbl),
5159 swStat->values.switchVals.swNum,
5160 (int) ulFromVal (caseVal->opval.val));
5162 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5163 rexpr->filename = 0;
5168 /*-----------------------------------------------------------------*/
5169 /* createDefault - creates the parse tree for the default statement */
5170 /*-----------------------------------------------------------------*/
5172 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5174 char defLbl[SDCC_NAME_MAX + 1];
5176 /* if the switch statement does not exist */
5177 /* then case is out of context */
5180 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5184 if (swStat->values.switchVals.swDefault)
5186 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5191 /* turn on the default flag */
5192 swStat->values.switchVals.swDefault = 1;
5194 /* create the label */
5195 SNPRINTF (defLbl, sizeof(defLbl),
5196 "_default_%d", swStat->values.switchVals.swNum);
5197 return createLabel (newSymbol (defLbl, 0), stmnt);
5200 /*-----------------------------------------------------------------*/
5201 /* createIf - creates the parsetree for the if statement */
5202 /*-----------------------------------------------------------------*/
5204 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5206 static int Lblnum = 0;
5208 symbol *ifTrue, *ifFalse, *ifEnd;
5210 /* if neither exists */
5211 if (!elseBody && !ifBody) {
5212 // if there are no side effects (i++, j() etc)
5213 if (!hasSEFcalls(condAst)) {
5218 /* create the labels */
5219 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5220 ifFalse = newSymbol (buffer, NestLevel);
5221 /* if no else body then end == false */
5226 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5227 ifEnd = newSymbol (buffer, NestLevel);
5230 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5231 ifTrue = newSymbol (buffer, NestLevel);
5235 /* attach the ifTrue label to the top of it body */
5236 ifBody = createLabel (ifTrue, ifBody);
5237 /* attach a goto end to the ifBody if else is present */
5240 ifBody = newNode (NULLOP, ifBody,
5242 newAst_VALUE (symbolVal (ifEnd)),
5244 /* put the elseLabel on the else body */
5245 elseBody = createLabel (ifFalse, elseBody);
5246 /* out the end at the end of the body */
5247 elseBody = newNode (NULLOP,
5249 createLabel (ifEnd, NULL));
5253 ifBody = newNode (NULLOP, ifBody,
5254 createLabel (ifFalse, NULL));
5256 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5257 if (IS_IFX (condAst))
5260 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5262 return newNode (NULLOP, ifTree,
5263 newNode (NULLOP, ifBody, elseBody));
5267 /*-----------------------------------------------------------------*/
5268 /* createDo - creates parse tree for do */
5271 /* _docontinue_n: */
5272 /* condition_expression +-> trueLabel -> _dobody_n */
5274 /* +-> falseLabel-> _dobreak_n */
5276 /*-----------------------------------------------------------------*/
5278 createDo (symbol * trueLabel, symbol * continueLabel,
5279 symbol * falseLabel, ast * condAst, ast * doBody)
5284 /* if the body does not exist then it is simple */
5287 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5288 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5289 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5290 doTree->trueLabel = continueLabel;
5291 doTree->falseLabel = NULL;
5293 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5297 /* otherwise we have a body */
5298 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5300 /* attach the body label to the top */
5301 doBody = createLabel (trueLabel, doBody);
5302 /* attach the continue label to end of body */
5303 doBody = newNode (NULLOP, doBody,
5304 createLabel (continueLabel, NULL));
5306 /* now put the break label at the end */
5307 if (IS_IFX (condAst))
5310 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5312 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5314 /* putting it together */
5315 return newNode (NULLOP, doBody, doTree);
5318 /*-----------------------------------------------------------------*/
5319 /* createFor - creates parse tree for 'for' statement */
5322 /* condExpr +-> trueLabel -> _forbody_n */
5324 /* +-> falseLabel-> _forbreak_n */
5327 /* _forcontinue_n: */
5329 /* goto _forcond_n ; */
5331 /*-----------------------------------------------------------------*/
5333 createFor (symbol * trueLabel, symbol * continueLabel,
5334 symbol * falseLabel, symbol * condLabel,
5335 ast * initExpr, ast * condExpr, ast * loopExpr,
5340 /* if loopexpression not present then we can generate it */
5341 /* the same way as a while */
5343 return newNode (NULLOP, initExpr,
5344 createWhile (trueLabel, continueLabel,
5345 falseLabel, condExpr, forBody));
5346 /* vanilla for statement */
5347 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5349 if (condExpr && !IS_IFX (condExpr))
5350 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5353 /* attach condition label to condition */
5354 condExpr = createLabel (condLabel, condExpr);
5356 /* attach body label to body */
5357 forBody = createLabel (trueLabel, forBody);
5359 /* attach continue to forLoop expression & attach */
5360 /* goto the forcond @ and of loopExpression */
5361 loopExpr = createLabel (continueLabel,
5365 newAst_VALUE (symbolVal (condLabel)),
5367 /* now start putting them together */
5368 forTree = newNode (NULLOP, initExpr, condExpr);
5369 forTree = newNode (NULLOP, forTree, forBody);
5370 forTree = newNode (NULLOP, forTree, loopExpr);
5371 /* finally add the break label */
5372 forTree = newNode (NULLOP, forTree,
5373 createLabel (falseLabel, NULL));
5377 /*-----------------------------------------------------------------*/
5378 /* createWhile - creates parse tree for while statement */
5379 /* the while statement will be created as follows */
5381 /* _while_continue_n: */
5382 /* condition_expression +-> trueLabel -> _while_boby_n */
5384 /* +-> falseLabel -> _while_break_n */
5385 /* _while_body_n: */
5387 /* goto _while_continue_n */
5388 /* _while_break_n: */
5389 /*-----------------------------------------------------------------*/
5391 createWhile (symbol * trueLabel, symbol * continueLabel,
5392 symbol * falseLabel, ast * condExpr, ast * whileBody)
5396 /* put the continue label */
5397 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5398 condExpr = createLabel (continueLabel, condExpr);
5399 condExpr->filename = NULL;
5400 condExpr->lineno = 0;
5402 /* put the body label in front of the body */
5403 whileBody = createLabel (trueLabel, whileBody);
5404 whileBody->filename = NULL;
5405 whileBody->lineno = 0;
5406 /* put a jump to continue at the end of the body */
5407 /* and put break label at the end of the body */
5408 whileBody = newNode (NULLOP,
5411 newAst_VALUE (symbolVal (continueLabel)),
5412 createLabel (falseLabel, NULL)));
5414 /* put it all together */
5415 if (IS_IFX (condExpr))
5416 whileTree = condExpr;
5419 whileTree = newNode (IFX, condExpr, NULL);
5420 /* put the true & false labels in place */
5421 whileTree->trueLabel = trueLabel;
5422 whileTree->falseLabel = falseLabel;
5425 return newNode (NULLOP, whileTree, whileBody);
5428 /*-----------------------------------------------------------------*/
5429 /* isShiftRightLitVal _BitAndLitVal - helper function */
5430 /*-----------------------------------------------------------------*/
5432 isShiftRightLitVal_BitAndLitVal (ast * tree)
5434 /* if this is not a bit and */
5435 if (!IS_BITAND (tree))
5438 /* will look for tree of the form
5439 ( expr >> litval2) & litval1 */
5440 if (!IS_AST_LIT_VALUE (tree->right))
5443 if (!IS_RIGHT_OP (tree->left))
5446 if (!IS_AST_LIT_VALUE (tree->left->right))
5449 return tree->left->left;
5452 /*-----------------------------------------------------------------*/
5453 /* isBitAndPowOf2 - helper function */
5454 /*-----------------------------------------------------------------*/
5456 isBitAndPow2 (ast * tree)
5458 /* if this is not a bit and */
5459 if (!IS_BITAND (tree))
5462 /* will look for tree of the form
5463 ( expr & (1 << litval) */
5464 if (!IS_AST_LIT_VALUE (tree->right))
5467 return powof2 (AST_ULONG_VALUE (tree->right));
5470 /*-----------------------------------------------------------------*/
5471 /* optimizeGetHbit - get highest order bit of the expression */
5472 /*-----------------------------------------------------------------*/
5474 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5479 expr = isShiftRightLitVal_BitAndLitVal(tree);
5482 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5483 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5484 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5487 if (!expr && (resultType == RESULT_TYPE_BIT))
5490 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5496 /* make sure the port supports GETHBIT */
5497 if (port->hasExtBitOp
5498 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5501 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5504 /*-----------------------------------------------------------------*/
5505 /* optimizeGetAbit - get a single bit of the expression */
5506 /*-----------------------------------------------------------------*/
5508 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5513 expr = isShiftRightLitVal_BitAndLitVal(tree);
5516 if (AST_ULONG_VALUE (tree->right) != 1)
5518 count = tree->left->right;
5520 if (!expr && (resultType == RESULT_TYPE_BIT))
5522 int p2 = isBitAndPow2 (tree);
5526 count = newAst_VALUE (valueFromLit (p2));
5532 /* make sure the port supports GETABIT */
5533 if (port->hasExtBitOp
5534 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5537 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5541 /*-----------------------------------------------------------------*/
5542 /* optimizeGetByte - get a byte of the expression */
5543 /*-----------------------------------------------------------------*/
5545 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5551 expr = isShiftRightLitVal_BitAndLitVal(tree);
5554 i = AST_ULONG_VALUE (tree->left->right);
5555 count = tree->left->right;
5556 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5559 if (!expr && resultType == RESULT_TYPE_CHAR)
5561 /* if this is a right shift over a multiple of 8 */
5562 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5564 i = AST_ULONG_VALUE (tree->right);
5565 count = tree->right;
5569 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5572 /* make sure the port supports GETBYTE */
5573 if (port->hasExtBitOp
5574 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5577 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5580 /*-----------------------------------------------------------------*/
5581 /* optimizeGetWord - get two bytes of the expression */
5582 /*-----------------------------------------------------------------*/
5584 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5590 expr = isShiftRightLitVal_BitAndLitVal(tree);
5593 i = AST_ULONG_VALUE (tree->left->right);
5594 count = tree->left->right;
5595 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5598 if (!expr && resultType == RESULT_TYPE_INT)
5600 /* if this is a right shift over a multiple of 8 */
5601 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5603 i = AST_ULONG_VALUE (tree->right);
5604 count = tree->right;
5608 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5611 /* make sure the port supports GETWORD */
5612 if (port->hasExtBitOp
5613 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5616 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5619 /*-----------------------------------------------------------------*/
5620 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5621 /*-----------------------------------------------------------------*/
5623 optimizeRRCRLC (ast * root)
5625 /* will look for trees of the form
5626 (?expr << 1) | (?expr >> 7) or
5627 (?expr >> 7) | (?expr << 1) will make that
5628 into a RLC : operation ..
5630 (?expr >> 1) | (?expr << 7) or
5631 (?expr << 7) | (?expr >> 1) will make that
5632 into a RRC operation
5633 note : by 7 I mean (number of bits required to hold the
5635 /* if the root operation is not a | operation then not */
5636 if (!IS_BITOR (root))
5639 /* I have to think of a better way to match patterns this sucks */
5640 /* that aside let's start looking for the first case : I use a
5641 negative check a lot to improve the efficiency */
5642 /* (?expr << 1) | (?expr >> 7) */
5643 if (IS_LEFT_OP (root->left) &&
5644 IS_RIGHT_OP (root->right))
5647 if (!SPEC_USIGN (TETYPE (root->left->left)))
5650 if (!IS_AST_LIT_VALUE (root->left->right) ||
5651 !IS_AST_LIT_VALUE (root->right->right))
5654 /* make sure it is the same expression */
5655 if (!isAstEqual (root->left->left,
5659 if (AST_ULONG_VALUE (root->left->right) != 1)
5662 if (AST_ULONG_VALUE (root->right->right) !=
5663 (getSize (TTYPE (root->left->left)) * 8 - 1))
5666 /* make sure the port supports RLC */
5667 if (port->hasExtBitOp
5668 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5671 /* whew got the first case : create the AST */
5672 return newNode (RLC, root->left->left, NULL);
5676 /* check for second case */
5677 /* (?expr >> 7) | (?expr << 1) */
5678 if (IS_LEFT_OP (root->right) &&
5679 IS_RIGHT_OP (root->left))
5682 if (!SPEC_USIGN (TETYPE (root->left->left)))
5685 if (!IS_AST_LIT_VALUE (root->left->right) ||
5686 !IS_AST_LIT_VALUE (root->right->right))
5689 /* make sure it is the same symbol */
5690 if (!isAstEqual (root->left->left,
5694 if (AST_ULONG_VALUE (root->right->right) != 1)
5697 if (AST_ULONG_VALUE (root->left->right) !=
5698 (getSize (TTYPE (root->left->left)) * 8 - 1))
5701 /* make sure the port supports RLC */
5702 if (port->hasExtBitOp
5703 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5706 /* whew got the first case : create the AST */
5707 return newNode (RLC, root->left->left, NULL);
5712 /* third case for RRC */
5713 /* (?symbol >> 1) | (?symbol << 7) */
5714 if (IS_LEFT_OP (root->right) &&
5715 IS_RIGHT_OP (root->left))
5718 if (!SPEC_USIGN (TETYPE (root->left->left)))
5721 if (!IS_AST_LIT_VALUE (root->left->right) ||
5722 !IS_AST_LIT_VALUE (root->right->right))
5725 /* make sure it is the same symbol */
5726 if (!isAstEqual (root->left->left,
5730 if (AST_ULONG_VALUE (root->left->right) != 1)
5733 if (AST_ULONG_VALUE (root->right->right) !=
5734 (getSize (TTYPE (root->left->left)) * 8 - 1))
5737 /* make sure the port supports RRC */
5738 if (port->hasExtBitOp
5739 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5742 /* whew got the first case : create the AST */
5743 return newNode (RRC, root->left->left, NULL);
5747 /* fourth and last case for now */
5748 /* (?symbol << 7) | (?symbol >> 1) */
5749 if (IS_RIGHT_OP (root->right) &&
5750 IS_LEFT_OP (root->left))
5753 if (!SPEC_USIGN (TETYPE (root->left->left)))
5756 if (!IS_AST_LIT_VALUE (root->left->right) ||
5757 !IS_AST_LIT_VALUE (root->right->right))
5760 /* make sure it is the same symbol */
5761 if (!isAstEqual (root->left->left,
5765 if (AST_ULONG_VALUE (root->right->right) != 1)
5768 if (AST_ULONG_VALUE (root->left->right) !=
5769 (getSize (TTYPE (root->left->left)) * 8 - 1))
5772 /* make sure the port supports RRC */
5773 if (port->hasExtBitOp
5774 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5777 /* whew got the first case : create the AST */
5778 return newNode (RRC, root->left->left, NULL);
5782 /* not found return root */
5786 /*-----------------------------------------------------------------*/
5787 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5788 /*-----------------------------------------------------------------*/
5790 optimizeSWAP (ast * root)
5792 /* will look for trees of the form
5793 (?expr << 4) | (?expr >> 4) or
5794 (?expr >> 4) | (?expr << 4) will make that
5795 into a SWAP : operation ..
5796 note : by 4 I mean (number of bits required to hold the
5798 /* if the root operation is not a | operation then not */
5799 if (!IS_BITOR (root))
5802 /* (?expr << 4) | (?expr >> 4) */
5803 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5804 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5807 if (!SPEC_USIGN (TETYPE (root->left->left)))
5810 if (!IS_AST_LIT_VALUE (root->left->right) ||
5811 !IS_AST_LIT_VALUE (root->right->right))
5814 /* make sure it is the same expression */
5815 if (!isAstEqual (root->left->left,
5819 if (AST_ULONG_VALUE (root->left->right) !=
5820 (getSize (TTYPE (root->left->left)) * 4))
5823 if (AST_ULONG_VALUE (root->right->right) !=
5824 (getSize (TTYPE (root->left->left)) * 4))
5827 /* make sure the port supports SWAP */
5828 if (port->hasExtBitOp
5829 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5832 /* found it : create the AST */
5833 return newNode (SWAP, root->left->left, NULL);
5837 /* not found return root */
5841 /*-----------------------------------------------------------------*/
5842 /* optimizeCompare - optimizes compares for bit variables */
5843 /*-----------------------------------------------------------------*/
5845 optimizeCompare (ast * root)
5847 ast *optExpr = NULL;
5850 unsigned int litValue;
5852 /* if nothing then return nothing */
5856 /* if not a compare op then do leaves */
5857 if (!IS_COMPARE_OP (root))
5859 root->left = optimizeCompare (root->left);
5860 root->right = optimizeCompare (root->right);
5864 /* if left & right are the same then depending
5865 of the operation do */
5866 if (isAstEqual (root->left, root->right))
5868 switch (root->opval.op)
5873 optExpr = newAst_VALUE (constCharVal (0));
5878 optExpr = newAst_VALUE (constCharVal (1));
5882 return decorateType (optExpr, RESULT_TYPE_NONE);
5885 vleft = (root->left->type == EX_VALUE ?
5886 root->left->opval.val : NULL);
5888 vright = (root->right->type == EX_VALUE ?
5889 root->right->opval.val : NULL);
5891 /* if left is a BITVAR in BITSPACE */
5892 /* and right is a LITERAL then */
5893 /* optimize else do nothing */
5894 if (vleft && vright &&
5895 IS_BITVAR (vleft->etype) &&
5896 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5897 IS_LITERAL (vright->etype))
5900 /* if right side > 1 then comparison may never succeed */
5901 if ((litValue = (int) ulFromVal (vright)) > 1)
5903 werror (W_BAD_COMPARE);
5909 switch (root->opval.op)
5911 case '>': /* bit value greater than 1 cannot be */
5912 werror (W_BAD_COMPARE);
5916 case '<': /* bit value < 1 means 0 */
5918 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5921 case LE_OP: /* bit value <= 1 means no check */
5922 optExpr = newAst_VALUE (vright);
5925 case GE_OP: /* bit value >= 1 means only check for = */
5927 optExpr = newAst_VALUE (vleft);
5932 { /* literal is zero */
5933 switch (root->opval.op)
5935 case '<': /* bit value < 0 cannot be */
5936 werror (W_BAD_COMPARE);
5940 case '>': /* bit value > 0 means 1 */
5942 optExpr = newAst_VALUE (vleft);
5945 case LE_OP: /* bit value <= 0 means no check */
5946 case GE_OP: /* bit value >= 0 means no check */
5947 werror (W_BAD_COMPARE);
5951 case EQ_OP: /* bit == 0 means ! of bit */
5952 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5956 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5957 } /* end-of-if of BITVAR */
5963 /*-----------------------------------------------------------------*/
5964 /* addSymToBlock : adds the symbol to the first block we find */
5965 /*-----------------------------------------------------------------*/
5967 addSymToBlock (symbol * sym, ast * tree)
5969 /* reached end of tree or a leaf */
5970 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5974 if (IS_AST_OP (tree) &&
5975 tree->opval.op == BLOCK)
5978 symbol *lsym = copySymbol (sym);
5980 lsym->next = AST_VALUES (tree, sym);
5981 AST_VALUES (tree, sym) = lsym;
5985 addSymToBlock (sym, tree->left);
5986 addSymToBlock (sym, tree->right);
5989 /*-----------------------------------------------------------------*/
5990 /* processRegParms - do processing for register parameters */
5991 /*-----------------------------------------------------------------*/
5993 processRegParms (value * args, ast * body)
5997 if (IS_REGPARM (args->etype))
5998 addSymToBlock (args->sym, body);
6003 /*-----------------------------------------------------------------*/
6004 /* resetParmKey - resets the operandkeys for the symbols */
6005 /*-----------------------------------------------------------------*/
6006 DEFSETFUNC (resetParmKey)
6017 /*------------------------------------------------------------------*/
6018 /* fixupInlineLabel - change a label in an inlined function so that */
6019 /* it is always unique no matter how many times */
6020 /* the function is inlined. */
6021 /*------------------------------------------------------------------*/
6023 fixupInlineLabel (symbol * sym)
6025 char name[SDCC_NAME_MAX + 1];
6027 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
6028 strcpy (sym->name, name);
6031 /*------------------------------------------------------------------*/
6032 /* copyAstLoc - copy location information (file, line, block, etc.) */
6033 /* from one ast node to another */
6034 /*------------------------------------------------------------------*/
6036 copyAstLoc (ast * dest, ast * src)
6038 dest->filename = src->filename;
6039 dest->lineno = src->lineno;
6040 dest->level = src->level;
6041 dest->block = src->block;
6042 dest->seqPoint = src->seqPoint;
6045 /*-----------------------------------------------------------------*/
6046 /* fixupInline - perform various fixups on an inline function tree */
6047 /* to take into account that it is no longer a */
6048 /* stand-alone function. */
6049 /*-----------------------------------------------------------------*/
6051 fixupInline (ast * tree, int level)
6053 int savedBlockno = currBlockno;
6055 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6059 currBlockno = ++blockNo;
6062 /* Add any declared variables back into the symbol table */
6063 decls = tree->values.sym;
6066 decls->level = level;
6067 decls->block = currBlockno;
6068 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6069 decls = decls->next;
6073 tree->level = level;
6074 tree->block = currBlockno;
6076 /* Update symbols */
6077 if (IS_AST_VALUE (tree) &&
6078 tree->opval.val->sym)
6080 symbol * sym = tree->opval.val->sym;
6083 sym->block = currBlockno;
6086 SYM_SPIL_LOC (sym) = NULL;
6089 /* If the symbol is a label, we need to renumber it */
6091 fixupInlineLabel (sym);
6094 /* Update IFX target labels */
6095 if (tree->type == EX_OP && tree->opval.op == IFX)
6097 if (tree->trueLabel)
6098 fixupInlineLabel (tree->trueLabel);
6099 if (tree->falseLabel)
6100 fixupInlineLabel (tree->falseLabel);
6103 /* Replace RETURN with optional assignment and a GOTO to the end */
6104 /* of the inlined function */
6105 if (tree->type == EX_OP && tree->opval.op == RETURN)
6107 ast * assignTree = NULL;
6110 if (inlineState.retsym && tree->right)
6112 assignTree = newNode ('=',
6113 newAst_VALUE (symbolVal (inlineState.retsym)),
6115 copyAstLoc (assignTree, tree);
6118 gotoTree = newNode (GOTO,
6119 newAst_VALUE (symbolVal (inlineState.retlab)),
6121 copyAstLoc (gotoTree, tree);
6123 tree->opval.op = NULLOP;
6124 tree->left = assignTree;
6125 tree->right = gotoTree;
6128 /* Update any children */
6130 fixupInline (tree->left, level);
6132 fixupInline (tree->right, level);
6134 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6136 symbol * label = tree->left->opval.val->sym;
6138 label->key = labelKey++;
6139 /* Add this label back into the symbol table */
6140 addSym (LabelTab, label, label->name, label->level, 0, 0);
6143 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6146 currBlockno = savedBlockno;
6150 /*-----------------------------------------------------------------*/
6151 /* inlineAddDecl - add a variable declaration to an ast block. It */
6152 /* is also added to the symbol table if addSymTab */
6154 /*-----------------------------------------------------------------*/
6156 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6159 SYM_SPIL_LOC (sym) = NULL;
6163 symbol **decl = &(block->values.sym);
6165 sym->level = block->level;
6166 sym->block = block->block;
6170 if (strcmp ((*decl)->name, sym->name) == 0)
6172 decl = &( (*decl)->next );
6178 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6183 /*-----------------------------------------------------------------*/
6184 /* inlineTempVar - create a temporary variable for inlining */
6185 /*-----------------------------------------------------------------*/
6187 inlineTempVar (sym_link * type, int level)
6191 sym = newSymbol (genSymName(level), level );
6192 sym->type = copyLinkChain (type);
6193 sym->etype = getSpec(sym->type);
6194 SPEC_SCLS (sym->etype) = S_AUTO;
6195 SPEC_OCLS (sym->etype) = NULL;
6196 SPEC_EXTR (sym->etype) = 0;
6197 SPEC_STAT (sym->etype) = 0;
6198 if IS_SPEC (sym->type)
6199 SPEC_VOLATILE (sym->type) = 0;
6201 DCL_PTR_VOLATILE (sym->type) = 0;
6202 SPEC_ABSA (sym->etype) = 0;
6207 /*-----------------------------------------------------------------*/
6208 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6209 /*-----------------------------------------------------------------*/
6211 inlineFindParmRecurse (ast * parms, int *index)
6216 if (parms->type == EX_OP && parms->opval.op == PARAM)
6220 p=inlineFindParmRecurse (parms->left, index);
6223 p=inlineFindParmRecurse (parms->right, index);
6233 /*-----------------------------------------------------------------*/
6234 /* inlineFindParm - search an ast tree of parameters to find one */
6235 /* at a particular index (0=first parameter). */
6236 /* Returns NULL if not found. */
6237 /*-----------------------------------------------------------------*/
6239 inlineFindParm (ast * parms, int index)
6241 return inlineFindParmRecurse (parms, &index);
6244 /*-----------------------------------------------------------------*/
6245 /* expandInlineFuncs - replace calls to inline functions with the */
6246 /* function itself */
6247 /*-----------------------------------------------------------------*/
6249 expandInlineFuncs (ast * tree, ast * block)
6251 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6252 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6254 symbol * func = tree->left->opval.val->sym;
6257 /* The symbol is probably not bound yet, so find the real one */
6258 csym = findSymWithLevel (SymbolTab, func);
6262 /* Is this an inline function that we can inline? */
6263 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6265 symbol * retsym = NULL;
6273 /* Generate a label for the inlined function to branch to */
6274 /* in case it contains a return statement */
6275 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6278 inlineState.retlab = retlab;
6280 /* Build the subtree for the inlined function in the form: */
6281 /* { //inlinetree block */
6282 /* { //inlinetree2 block */
6283 /* inline_function_code; */
6287 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6288 copyAstLoc (temptree, tree);
6289 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6290 copyAstLoc (temptree, tree);
6291 temptree = newNode (BLOCK, NULL, temptree);
6292 copyAstLoc (temptree, tree);
6293 inlinetree2 = temptree;
6294 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6295 copyAstLoc (inlinetree, tree);
6297 /* To pass parameters to the inlined function, we need some */
6298 /* intermediate variables. This avoids scoping problems */
6299 /* when the parameter declaration names are used differently */
6300 /* during the function call. For example, a function */
6301 /* declared as func(int x, int y) but called as func(y,x). */
6302 /* { //inlinetree block */
6303 /* type1 temparg1 = argument1; */
6305 /* typen tempargn = argumentn; */
6306 /* { //inlinetree2 block */
6307 /* type1 param1 = temparg1; */
6309 /* typen paramn = tempargn; */
6310 /* inline_function_code; */
6314 args = FUNC_ARGS (func->type);
6321 ast * passedarg = inlineFindParm (tree->right, argIndex);
6325 werror(E_TOO_FEW_PARMS);
6329 temparg = inlineTempVar (args->sym->type, tree->level+1);
6330 inlineAddDecl (temparg, inlinetree, FALSE);
6332 assigntree = newNode ('=',
6333 newAst_VALUE (symbolVal (temparg)),
6335 assigntree->initMode=1; // tell that assignment is initializer
6336 inlinetree->right = newNode (NULLOP,
6340 parm = copySymbol (args->sym);
6341 inlineAddDecl (parm, inlinetree2, FALSE);
6344 assigntree = newNode ('=',
6345 newAst_VALUE (symbolVal (parm)),
6346 newAst_VALUE (symbolVal (temparg)));
6347 assigntree->initMode=1; // tell that assignment is initializer
6348 inlinetree2->right = newNode (NULLOP,
6350 inlinetree2->right);
6356 /* Handle the return type */
6357 if (!IS_VOID (func->type->next))
6359 /* Create a temporary symbol to hold the return value and */
6360 /* join it with the inlined function using the comma */
6361 /* operator. The fixupInline function will take care of */
6362 /* changing return statements into assignments to retsym. */
6363 /* (parameter passing and return label omitted for clarity) */
6364 /* rettype retsym; */
6366 /* {{inline_function_code}}, retsym */
6368 retsym = inlineTempVar (func->type->next, tree->level);
6369 inlineAddDecl (retsym, block, TRUE);
6371 tree->opval.op = ',';
6372 tree->left = inlinetree;
6373 tree->right = newAst_VALUE (symbolVal (retsym));
6377 tree->opval.op = NULLOP;
6379 tree->right = inlinetree;
6381 inlineState.retsym = retsym;
6383 /* Renumber the various internal counters on the inlined */
6384 /* function's tree nodes and symbols. Add the inlined */
6385 /* function's local variables to the appropriate scope(s). */
6386 /* Convert inlined return statements to an assignment to */
6387 /* retsym (if needed) and a goto retlab. */
6388 fixupInline (inlinetree, inlinetree->level);
6389 inlineState.count++;
6393 /* Recursively continue to search for functions to inline. */
6394 if (IS_AST_OP (tree))
6396 if (tree->opval.op == BLOCK)
6400 expandInlineFuncs (tree->left, block);
6402 expandInlineFuncs (tree->right, block);
6406 /*-----------------------------------------------------------------*/
6407 /* createFunction - This is the key node that calls the iCode for */
6408 /* generating the code for a function. Note code */
6409 /* is generated function by function, later when */
6410 /* add inter-procedural analysis this will change */
6411 /*-----------------------------------------------------------------*/
6413 createFunction (symbol * name, ast * body)
6419 iCode *piCode = NULL;
6421 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6422 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6424 /* if check function return 0 then some problem */
6425 if (checkFunction (name, NULL) == 0)
6428 /* create a dummy block if none exists */
6430 body = newNode (BLOCK, NULL, NULL);
6434 /* check if the function name already in the symbol table */
6435 if ((csym = findSym (SymbolTab, NULL, name->name)))
6438 /* special case for compiler defined functions
6439 we need to add the name to the publics list : this
6440 actually means we are now compiling the compiler
6444 addSet (&publics, name);
6449 addSymChain (&name);
6450 allocVariables (name);
6452 name->lastLine = lexLineno;
6455 /* set the stack pointer */
6456 stackPtr = -port->stack.direction * port->stack.call_overhead;
6459 if (IFFUNC_ISISR (name->type))
6460 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6462 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6464 if (options.useXstack)
6465 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6467 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6470 fetype = getSpec (name->type); /* get the specifier for the function */
6471 /* if this is a reentrant function then */
6472 if (IFFUNC_ISREENT (name->type))
6475 inlineState.count = 0;
6476 expandInlineFuncs (body, NULL);
6478 if (FUNC_ISINLINE (name->type))
6479 name->funcTree = copyAst (body);
6481 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6483 /* do processing for parameters that are passed in registers */
6484 processRegParms (FUNC_ARGS(name->type), body);
6486 /* set the stack pointer */
6490 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6492 /* allocate & autoinit the block variables */
6493 processBlockVars (body, &stack, ALLOCATE);
6495 /* name needs to be mangled */
6496 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6498 body = resolveSymbols (body); /* resolve the symbols */
6499 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6501 /* save the stack information */
6502 if (options.useXstack)
6503 name->xstack = SPEC_STAK (fetype) = stack;
6505 name->stack = SPEC_STAK (fetype) = stack;
6507 ex = newAst_VALUE (symbolVal (name)); /* create name */
6508 ex = newNode (FUNCTION, ex, body);
6509 ex->values.args = FUNC_ARGS(name->type);
6511 if (options.dump_tree)
6516 /* Do not generate code for inline functions unless extern also. */
6518 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6521 /* Temporary hack: always generate code for static inline functions. */
6522 /* Ideally static inline functions should only be generated if needed. */
6523 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6527 /* create the node & generate intermediate code */
6529 codeOutBuf = &code->oBuf;
6530 piCode = iCodeFromAst (ex);
6531 name->generated = 1;
6536 eBBlockFromiCode (piCode);
6538 /* if there are any statics then do them */
6541 GcurMemmap = statsg;
6542 codeOutBuf = &statsg->oBuf;
6543 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6549 /* dealloc the block variables */
6550 processBlockVars (body, &stack, DEALLOCATE);
6551 outputDebugStackSymbols();
6552 /* deallocate paramaters */
6553 deallocParms (FUNC_ARGS(name->type));
6555 if (IFFUNC_ISREENT (name->type))
6558 /* we are done freeup memory & cleanup */
6560 if (port->reset_labelKey)
6563 FUNC_HASBODY(name->type) = 1;
6564 addSet (&operKeyReset, name);
6565 applyToSet (operKeyReset, resetParmKey);
6570 cleanUpLevel (LabelTab, 0);
6571 cleanUpBlock (StructTab, 1);
6572 cleanUpBlock (TypedefTab, 1);
6574 xstack->syms = NULL;
6575 istack->syms = NULL;
6580 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6581 /*-----------------------------------------------------------------*/
6582 /* ast_print : prints the ast (for debugging purposes) */
6583 /*-----------------------------------------------------------------*/
6585 void ast_print (ast * tree, FILE *outfile, int indent)
6590 /* can print only decorated trees */
6591 if (!tree->decorated) return;
6593 /* if any child is an error | this one is an error do nothing */
6594 if (tree->isError ||
6595 (tree->left && tree->left->isError) ||
6596 (tree->right && tree->right->isError)) {
6597 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6601 /* print the line */
6602 /* if not block & function */
6603 if (tree->type == EX_OP &&
6604 (tree->opval.op != FUNCTION &&
6605 tree->opval.op != BLOCK &&
6606 tree->opval.op != NULLOP)) {
6609 if (tree->opval.op == FUNCTION) {
6611 value *args=FUNC_ARGS(tree->left->opval.val->type);
6612 fprintf(outfile,"FUNCTION (%s=%p) type (",
6613 tree->left->opval.val->name, tree);
6614 printTypeChain (tree->left->opval.val->type->next,outfile);
6615 fprintf(outfile,") args (");
6618 fprintf (outfile, ", ");
6620 printTypeChain (args ? args->type : NULL, outfile);
6622 args= args ? args->next : NULL;
6624 fprintf(outfile,")\n");
6625 ast_print(tree->left,outfile,indent);
6626 ast_print(tree->right,outfile,indent);
6629 if (tree->opval.op == BLOCK) {
6630 symbol *decls = tree->values.sym;
6631 INDENT(indent,outfile);
6632 fprintf(outfile,"{\n");
6634 INDENT(indent+2,outfile);
6635 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6636 decls->name, decls);
6637 printTypeChain(decls->type,outfile);
6638 fprintf(outfile,")\n");
6640 decls = decls->next;
6642 ast_print(tree->right,outfile,indent+2);
6643 INDENT(indent,outfile);
6644 fprintf(outfile,"}\n");
6647 if (tree->opval.op == NULLOP) {
6648 ast_print(tree->left,outfile,indent);
6649 ast_print(tree->right,outfile,indent);
6652 INDENT(indent,outfile);
6654 /*------------------------------------------------------------------*/
6655 /*----------------------------*/
6656 /* leaf has been reached */
6657 /*----------------------------*/
6658 /* if this is of type value */
6659 /* just get the type */
6660 if (tree->type == EX_VALUE) {
6662 if (IS_LITERAL (tree->opval.val->etype)) {
6663 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6664 if (SPEC_USIGN (tree->opval.val->etype))
6665 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6667 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6668 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6669 floatFromVal(tree->opval.val));
6670 } else if (tree->opval.val->sym) {
6671 /* if the undefined flag is set then give error message */
6672 if (tree->opval.val->sym->undefined) {
6673 fprintf(outfile,"UNDEFINED SYMBOL ");
6675 fprintf(outfile,"SYMBOL ");
6677 fprintf(outfile,"(%s=%p @ %p)",
6678 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6681 fprintf(outfile," type (");
6682 printTypeChain(tree->ftype,outfile);
6683 fprintf(outfile,")\n");
6685 fprintf(outfile,"\n");
6690 /* if type link for the case of cast */
6691 if (tree->type == EX_LINK) {
6692 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6693 printTypeChain(tree->opval.lnk,outfile);
6694 fprintf(outfile,")\n");
6699 /* depending on type of operator do */
6701 switch (tree->opval.op) {
6702 /*------------------------------------------------------------------*/
6703 /*----------------------------*/
6705 /*----------------------------*/
6707 fprintf(outfile,"ARRAY_OP (%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 /*----------------------------*/
6717 /*----------------------------*/
6719 fprintf(outfile,"STRUCT_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 /* struct/union pointer */
6729 /*----------------------------*/
6731 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6732 printTypeChain(tree->ftype,outfile);
6733 fprintf(outfile,")\n");
6734 ast_print(tree->left,outfile,indent+2);
6735 ast_print(tree->right,outfile,indent+2);
6738 /*------------------------------------------------------------------*/
6739 /*----------------------------*/
6740 /* ++/-- operation */
6741 /*----------------------------*/
6744 fprintf(outfile,"post-");
6746 fprintf(outfile,"pre-");
6747 fprintf(outfile,"INC_OP (%p) type (",tree);
6748 printTypeChain(tree->ftype,outfile);
6749 fprintf(outfile,")\n");
6750 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6751 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6756 fprintf(outfile,"post-");
6758 fprintf(outfile,"pre-");
6759 fprintf(outfile,"DEC_OP (%p) type (",tree);
6760 printTypeChain(tree->ftype,outfile);
6761 fprintf(outfile,")\n");
6762 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6763 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6766 /*------------------------------------------------------------------*/
6767 /*----------------------------*/
6769 /*----------------------------*/
6772 fprintf(outfile,"& (%p) type (",tree);
6773 printTypeChain(tree->ftype,outfile);
6774 fprintf(outfile,")\n");
6775 ast_print(tree->left,outfile,indent+2);
6776 ast_print(tree->right,outfile,indent+2);
6778 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6779 printTypeChain(tree->ftype,outfile);
6780 fprintf(outfile,")\n");
6781 ast_print(tree->left,outfile,indent+2);
6782 ast_print(tree->right,outfile,indent+2);
6785 /*----------------------------*/
6787 /*----------------------------*/
6789 fprintf(outfile,"OR (%p) type (",tree);
6790 printTypeChain(tree->ftype,outfile);
6791 fprintf(outfile,")\n");
6792 ast_print(tree->left,outfile,indent+2);
6793 ast_print(tree->right,outfile,indent+2);
6795 /*------------------------------------------------------------------*/
6796 /*----------------------------*/
6798 /*----------------------------*/
6800 fprintf(outfile,"XOR (%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);
6807 /*------------------------------------------------------------------*/
6808 /*----------------------------*/
6810 /*----------------------------*/
6812 fprintf(outfile,"DIV (%p) type (",tree);
6813 printTypeChain(tree->ftype,outfile);
6814 fprintf(outfile,")\n");
6815 ast_print(tree->left,outfile,indent+2);
6816 ast_print(tree->right,outfile,indent+2);
6818 /*------------------------------------------------------------------*/
6819 /*----------------------------*/
6821 /*----------------------------*/
6823 fprintf(outfile,"MOD (%p) type (",tree);
6824 printTypeChain(tree->ftype,outfile);
6825 fprintf(outfile,")\n");
6826 ast_print(tree->left,outfile,indent+2);
6827 ast_print(tree->right,outfile,indent+2);
6830 /*------------------------------------------------------------------*/
6831 /*----------------------------*/
6832 /* address dereference */
6833 /*----------------------------*/
6834 case '*': /* can be unary : if right is null then unary operation */
6836 fprintf(outfile,"DEREF (%p) type (",tree);
6837 printTypeChain(tree->ftype,outfile);
6838 fprintf(outfile,")\n");
6839 ast_print(tree->left,outfile,indent+2);
6842 /*------------------------------------------------------------------*/
6843 /*----------------------------*/
6844 /* multiplication */
6845 /*----------------------------*/
6846 fprintf(outfile,"MULT (%p) type (",tree);
6847 printTypeChain(tree->ftype,outfile);
6848 fprintf(outfile,")\n");
6849 ast_print(tree->left,outfile,indent+2);
6850 ast_print(tree->right,outfile,indent+2);
6854 /*------------------------------------------------------------------*/
6855 /*----------------------------*/
6856 /* unary '+' operator */
6857 /*----------------------------*/
6861 fprintf(outfile,"UPLUS (%p) type (",tree);
6862 printTypeChain(tree->ftype,outfile);
6863 fprintf(outfile,")\n");
6864 ast_print(tree->left,outfile,indent+2);
6866 /*------------------------------------------------------------------*/
6867 /*----------------------------*/
6869 /*----------------------------*/
6870 fprintf(outfile,"ADD (%p) type (",tree);
6871 printTypeChain(tree->ftype,outfile);
6872 fprintf(outfile,")\n");
6873 ast_print(tree->left,outfile,indent+2);
6874 ast_print(tree->right,outfile,indent+2);
6877 /*------------------------------------------------------------------*/
6878 /*----------------------------*/
6880 /*----------------------------*/
6881 case '-': /* can be unary */
6883 fprintf(outfile,"UMINUS (%p) type (",tree);
6884 printTypeChain(tree->ftype,outfile);
6885 fprintf(outfile,")\n");
6886 ast_print(tree->left,outfile,indent+2);
6888 /*------------------------------------------------------------------*/
6889 /*----------------------------*/
6891 /*----------------------------*/
6892 fprintf(outfile,"SUB (%p) type (",tree);
6893 printTypeChain(tree->ftype,outfile);
6894 fprintf(outfile,")\n");
6895 ast_print(tree->left,outfile,indent+2);
6896 ast_print(tree->right,outfile,indent+2);
6899 /*------------------------------------------------------------------*/
6900 /*----------------------------*/
6902 /*----------------------------*/
6904 fprintf(outfile,"COMPL (%p) type (",tree);
6905 printTypeChain(tree->ftype,outfile);
6906 fprintf(outfile,")\n");
6907 ast_print(tree->left,outfile,indent+2);
6909 /*------------------------------------------------------------------*/
6910 /*----------------------------*/
6912 /*----------------------------*/
6914 fprintf(outfile,"NOT (%p) type (",tree);
6915 printTypeChain(tree->ftype,outfile);
6916 fprintf(outfile,")\n");
6917 ast_print(tree->left,outfile,indent+2);
6919 /*------------------------------------------------------------------*/
6920 /*----------------------------*/
6922 /*----------------------------*/
6924 fprintf(outfile,"RRC (%p) type (",tree);
6925 printTypeChain(tree->ftype,outfile);
6926 fprintf(outfile,")\n");
6927 ast_print(tree->left,outfile,indent+2);
6931 fprintf(outfile,"RLC (%p) type (",tree);
6932 printTypeChain(tree->ftype,outfile);
6933 fprintf(outfile,")\n");
6934 ast_print(tree->left,outfile,indent+2);
6937 fprintf(outfile,"SWAP (%p) type (",tree);
6938 printTypeChain(tree->ftype,outfile);
6939 fprintf(outfile,")\n");
6940 ast_print(tree->left,outfile,indent+2);
6943 fprintf(outfile,"GETHBIT (%p) type (",tree);
6944 printTypeChain(tree->ftype,outfile);
6945 fprintf(outfile,")\n");
6946 ast_print(tree->left,outfile,indent+2);
6949 fprintf(outfile,"GETABIT (%p) type (",tree);
6950 printTypeChain(tree->ftype,outfile);
6951 fprintf(outfile,")\n");
6952 ast_print(tree->left,outfile,indent+2);
6953 ast_print(tree->right,outfile,indent+2);
6956 fprintf(outfile,"GETBYTE (%p) type (",tree);
6957 printTypeChain(tree->ftype,outfile);
6958 fprintf(outfile,")\n");
6959 ast_print(tree->left,outfile,indent+2);
6960 ast_print(tree->right,outfile,indent+2);
6963 fprintf(outfile,"GETWORD (%p) type (",tree);
6964 printTypeChain(tree->ftype,outfile);
6965 fprintf(outfile,")\n");
6966 ast_print(tree->left,outfile,indent+2);
6967 ast_print(tree->right,outfile,indent+2);
6970 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6971 printTypeChain(tree->ftype,outfile);
6972 fprintf(outfile,")\n");
6973 ast_print(tree->left,outfile,indent+2);
6974 ast_print(tree->right,outfile,indent+2);
6977 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6978 printTypeChain(tree->ftype,outfile);
6979 fprintf(outfile,")\n");
6980 ast_print(tree->left,outfile,indent+2);
6981 ast_print(tree->right,outfile,indent+2);
6983 /*------------------------------------------------------------------*/
6984 /*----------------------------*/
6986 /*----------------------------*/
6987 case CAST: /* change the type */
6988 fprintf(outfile,"CAST (%p) from type (",tree);
6989 printTypeChain(tree->right->ftype,outfile);
6990 fprintf(outfile,") to type (");
6991 printTypeChain(tree->ftype,outfile);
6992 fprintf(outfile,")\n");
6993 ast_print(tree->right,outfile,indent+2);
6997 fprintf(outfile,"ANDAND (%p) type (",tree);
6998 printTypeChain(tree->ftype,outfile);
6999 fprintf(outfile,")\n");
7000 ast_print(tree->left,outfile,indent+2);
7001 ast_print(tree->right,outfile,indent+2);
7004 fprintf(outfile,"OROR (%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 /*------------------------------------------------------------------*/
7012 /*----------------------------*/
7013 /* comparison operators */
7014 /*----------------------------*/
7016 fprintf(outfile,"GT(>) (%p) type (",tree);
7017 printTypeChain(tree->ftype,outfile);
7018 fprintf(outfile,")\n");
7019 ast_print(tree->left,outfile,indent+2);
7020 ast_print(tree->right,outfile,indent+2);
7023 fprintf(outfile,"LT(<) (%p) type (",tree);
7024 printTypeChain(tree->ftype,outfile);
7025 fprintf(outfile,")\n");
7026 ast_print(tree->left,outfile,indent+2);
7027 ast_print(tree->right,outfile,indent+2);
7030 fprintf(outfile,"LE(<=) (%p) type (",tree);
7031 printTypeChain(tree->ftype,outfile);
7032 fprintf(outfile,")\n");
7033 ast_print(tree->left,outfile,indent+2);
7034 ast_print(tree->right,outfile,indent+2);
7037 fprintf(outfile,"GE(>=) (%p) type (",tree);
7038 printTypeChain(tree->ftype,outfile);
7039 fprintf(outfile,")\n");
7040 ast_print(tree->left,outfile,indent+2);
7041 ast_print(tree->right,outfile,indent+2);
7044 fprintf(outfile,"EQ(==) (%p) type (",tree);
7045 printTypeChain(tree->ftype,outfile);
7046 fprintf(outfile,")\n");
7047 ast_print(tree->left,outfile,indent+2);
7048 ast_print(tree->right,outfile,indent+2);
7051 fprintf(outfile,"NE(!=) (%p) type (",tree);
7052 printTypeChain(tree->ftype,outfile);
7053 fprintf(outfile,")\n");
7054 ast_print(tree->left,outfile,indent+2);
7055 ast_print(tree->right,outfile,indent+2);
7056 /*------------------------------------------------------------------*/
7057 /*----------------------------*/
7059 /*----------------------------*/
7060 case SIZEOF: /* evaluate wihout code generation */
7061 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7064 /*------------------------------------------------------------------*/
7065 /*----------------------------*/
7066 /* conditional operator '?' */
7067 /*----------------------------*/
7069 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7070 printTypeChain(tree->ftype,outfile);
7071 fprintf(outfile,")\n");
7072 ast_print(tree->left,outfile,indent+2);
7073 ast_print(tree->right,outfile,indent+2);
7077 fprintf(outfile,"COLON(:) (%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 /*------------------------------------------------------------------*/
7085 /*----------------------------*/
7086 /* assignment operators */
7087 /*----------------------------*/
7089 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7090 printTypeChain(tree->ftype,outfile);
7091 fprintf(outfile,")\n");
7092 ast_print(tree->left,outfile,indent+2);
7093 ast_print(tree->right,outfile,indent+2);
7096 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7097 printTypeChain(tree->ftype,outfile);
7098 fprintf(outfile,")\n");
7099 ast_print(tree->left,outfile,indent+2);
7100 ast_print(tree->right,outfile,indent+2);
7103 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7104 printTypeChain(tree->ftype,outfile);
7105 fprintf(outfile,")\n");
7106 ast_print(tree->left,outfile,indent+2);
7107 ast_print(tree->right,outfile,indent+2);
7110 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7111 printTypeChain(tree->ftype,outfile);
7112 fprintf(outfile,")\n");
7113 ast_print(tree->left,outfile,indent+2);
7114 ast_print(tree->right,outfile,indent+2);
7117 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7118 printTypeChain(tree->ftype,outfile);
7119 fprintf(outfile,")\n");
7120 ast_print(tree->left,outfile,indent+2);
7121 ast_print(tree->right,outfile,indent+2);
7124 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7125 printTypeChain(tree->ftype,outfile);
7126 fprintf(outfile,")\n");
7127 ast_print(tree->left,outfile,indent+2);
7128 ast_print(tree->right,outfile,indent+2);
7131 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7132 printTypeChain(tree->ftype,outfile);
7133 fprintf(outfile,")\n");
7134 ast_print(tree->left,outfile,indent+2);
7135 ast_print(tree->right,outfile,indent+2);
7137 /*------------------------------------------------------------------*/
7138 /*----------------------------*/
7140 /*----------------------------*/
7142 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7143 printTypeChain(tree->ftype,outfile);
7144 fprintf(outfile,")\n");
7145 ast_print(tree->left,outfile,indent+2);
7146 ast_print(tree->right,outfile,indent+2);
7148 /*------------------------------------------------------------------*/
7149 /*----------------------------*/
7151 /*----------------------------*/
7153 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7154 printTypeChain(tree->ftype,outfile);
7155 fprintf(outfile,")\n");
7156 ast_print(tree->left,outfile,indent+2);
7157 ast_print(tree->right,outfile,indent+2);
7159 /*------------------------------------------------------------------*/
7160 /*----------------------------*/
7161 /* straight assignemnt */
7162 /*----------------------------*/
7164 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7165 printTypeChain(tree->ftype,outfile);
7166 fprintf(outfile,")\n");
7167 ast_print(tree->left,outfile,indent+2);
7168 ast_print(tree->right,outfile,indent+2);
7170 /*------------------------------------------------------------------*/
7171 /*----------------------------*/
7172 /* comma operator */
7173 /*----------------------------*/
7175 fprintf(outfile,"COMMA(,) (%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);
7181 /*------------------------------------------------------------------*/
7182 /*----------------------------*/
7184 /*----------------------------*/
7187 fprintf(outfile,"CALL (%p) type (",tree);
7188 printTypeChain(tree->ftype,outfile);
7189 fprintf(outfile,")\n");
7190 ast_print(tree->left,outfile,indent+2);
7191 ast_print(tree->right,outfile,indent+2);
7194 fprintf(outfile,"PARMS\n");
7195 ast_print(tree->left,outfile,indent+2);
7196 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7197 ast_print(tree->right,outfile,indent+2);
7200 /*------------------------------------------------------------------*/
7201 /*----------------------------*/
7202 /* return statement */
7203 /*----------------------------*/
7205 fprintf(outfile,"RETURN (%p) type (",tree);
7207 printTypeChain(tree->right->ftype,outfile);
7209 fprintf(outfile,")\n");
7210 ast_print(tree->right,outfile,indent+2);
7212 /*------------------------------------------------------------------*/
7213 /*----------------------------*/
7214 /* label statement */
7215 /*----------------------------*/
7217 fprintf(outfile,"LABEL (%p)\n",tree);
7218 ast_print(tree->left,outfile,indent+2);
7219 ast_print(tree->right,outfile,indent);
7221 /*------------------------------------------------------------------*/
7222 /*----------------------------*/
7223 /* switch statement */
7224 /*----------------------------*/
7228 fprintf(outfile,"SWITCH (%p) ",tree);
7229 ast_print(tree->left,outfile,0);
7230 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7231 INDENT(indent+2,outfile);
7232 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7233 (int) ulFromVal(val),
7234 tree->values.switchVals.swNum,
7235 (int) ulFromVal(val));
7237 ast_print(tree->right,outfile,indent);
7240 /*------------------------------------------------------------------*/
7241 /*----------------------------*/
7243 /*----------------------------*/
7245 fprintf(outfile,"IF (%p) \n",tree);
7246 ast_print(tree->left,outfile,indent+2);
7247 if (tree->trueLabel) {
7248 INDENT(indent+2,outfile);
7249 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7251 if (tree->falseLabel) {
7252 INDENT(indent+2,outfile);
7253 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7255 ast_print(tree->right,outfile,indent+2);
7257 /*----------------------------*/
7258 /* goto Statement */
7259 /*----------------------------*/
7261 fprintf(outfile,"GOTO (%p) \n",tree);
7262 ast_print(tree->left,outfile,indent+2);
7263 fprintf(outfile,"\n");
7265 /*------------------------------------------------------------------*/
7266 /*----------------------------*/
7268 /*----------------------------*/
7270 fprintf(outfile,"FOR (%p) \n",tree);
7271 if (AST_FOR( tree, initExpr)) {
7272 INDENT(indent+2,outfile);
7273 fprintf(outfile,"INIT EXPR ");
7274 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7276 if (AST_FOR( tree, condExpr)) {
7277 INDENT(indent+2,outfile);
7278 fprintf(outfile,"COND EXPR ");
7279 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7281 if (AST_FOR( tree, loopExpr)) {
7282 INDENT(indent+2,outfile);
7283 fprintf(outfile,"LOOP EXPR ");
7284 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7286 fprintf(outfile,"FOR LOOP BODY \n");
7287 ast_print(tree->left,outfile,indent+2);
7290 fprintf(outfile,"CRITICAL (%p) \n",tree);
7291 ast_print(tree->left,outfile,indent+2);
7299 ast_print(t,stdout,0);
7302 /*-----------------------------------------------------------------*/
7303 /* astErrors : returns non-zero if errors present in tree */
7304 /*-----------------------------------------------------------------*/
7305 int astErrors(ast *t)
7314 if (t->type == EX_VALUE
7315 && t->opval.val->sym
7316 && t->opval.val->sym->undefined)
7319 errors += astErrors(t->left);
7320 errors += astErrors(t->right);