1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
545 /* if this is a label resolve it from the labelTab */
546 if (IS_AST_VALUE (tree) &&
547 tree->opval.val->sym &&
548 tree->opval.val->sym->islbl)
550 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
551 tree->opval.val->sym->name);
554 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
555 tree->opval.val->sym->name);
557 tree->opval.val->sym = csym;
559 goto resolveChildren;
562 /* do only for leafs */
563 if (IS_AST_VALUE (tree) &&
564 tree->opval.val->sym &&
565 !tree->opval.val->sym->implicit)
567 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
569 /* if found in the symbol table & they are not the same */
570 if (csym && tree->opval.val->sym != csym)
572 tree->opval.val->sym = csym;
573 tree->opval.val->type = csym->type;
574 tree->opval.val->etype = csym->etype;
577 /* if not found in the symbol table */
578 /* mark it as undefined & assume it */
579 /* is an integer in data space */
580 if (!csym && !tree->opval.val->sym->implicit)
582 /* if this is a function name then */
583 /* mark it as returning an int */
586 tree->opval.val->sym->type = newLink (DECLARATOR);
587 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
588 tree->opval.val->sym->type->next =
589 tree->opval.val->sym->etype = newIntLink ();
590 tree->opval.val->etype = tree->opval.val->etype;
591 tree->opval.val->type = tree->opval.val->sym->type;
592 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
593 tree->opval.val->sym->name);
594 //tree->opval.val->sym->undefined = 1;
595 allocVariables (tree->opval.val->sym);
599 tree->opval.val->sym->undefined = 1;
600 tree->opval.val->type =
601 tree->opval.val->etype = newIntLink ();
602 tree->opval.val->sym->type =
603 tree->opval.val->sym->etype = newIntLink ();
609 resolveSymbols (tree->left);
610 resolveSymbols (tree->right);
615 /*------------------------------------------------------------------------*/
616 /* setAstFileLine - walks a ast tree & sets the file name and line number */
617 /*------------------------------------------------------------------------*/
618 int setAstFileLine (ast * tree, char *filename, int lineno)
623 tree->filename = filename;
624 tree->lineno = lineno;
625 setAstFileLine (tree->left, filename, lineno);
626 setAstFileLine (tree->right, filename, lineno);
630 /*-----------------------------------------------------------------*/
631 /* funcOfType :- function of type with name */
632 /*-----------------------------------------------------------------*/
634 funcOfType (char *name, sym_link * type, sym_link * argType,
638 /* create the symbol */
639 sym = newSymbol (name, 0);
641 /* setup return value */
642 sym->type = newLink (DECLARATOR);
643 DCL_TYPE (sym->type) = FUNCTION;
644 sym->type->next = copyLinkChain (type);
645 sym->etype = getSpec (sym->type);
646 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
648 /* if arguments required */
652 args = FUNC_ARGS(sym->type) = newValue ();
656 args->type = copyLinkChain (argType);
657 args->etype = getSpec (args->type);
658 SPEC_EXTR(args->etype)=1;
661 args = args->next = newValue ();
668 allocVariables (sym);
673 /*-----------------------------------------------------------------*/
674 /* funcOfTypeVarg :- function of type with name and argtype */
675 /*-----------------------------------------------------------------*/
677 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
682 /* create the symbol */
683 sym = newSymbol (name, 0);
685 /* setup return value */
686 sym->type = newLink (DECLARATOR);
687 DCL_TYPE (sym->type) = FUNCTION;
688 sym->type->next = typeFromStr(rtype);
689 sym->etype = getSpec (sym->type);
691 /* if arguments required */
694 args = FUNC_ARGS(sym->type) = newValue ();
696 for ( i = 0 ; i < nArgs ; i++ ) {
697 args->type = typeFromStr(atypes[i]);
698 args->etype = getSpec (args->type);
699 SPEC_EXTR(args->etype)=1;
700 if ((i + 1) == nArgs) break;
701 args = args->next = newValue ();
708 allocVariables (sym);
713 /*-----------------------------------------------------------------*/
714 /* reverseParms - will reverse a parameter tree */
715 /*-----------------------------------------------------------------*/
717 reverseParms (ast * ptree)
723 /* top down if we find a nonParm tree then quit */
724 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
726 /* The various functions expect the parameter tree to be right heavy. */
727 /* Rotate the tree to be left heavy so that after reversal it is */
728 /* right heavy again. */
729 while ((ttree = ptree->right) && ttree->type == EX_OP &&
730 ttree->opval.op == PARAM)
732 ptree->right = ttree->right;
733 ttree->right = ttree->left;
734 ttree->left = ptree->left;
740 ptree->left = ptree->right;
741 ptree->right = ttree;
743 reverseParms (ptree->left);
744 reverseParms (ptree->right);
750 /*-----------------------------------------------------------------*/
751 /* processParms - makes sure the parameters are okay and do some */
752 /* processing with them */
753 /*-----------------------------------------------------------------*/
755 processParms (ast *func,
758 int *parmNumber, /* unused, although updated */
761 RESULT_TYPE resultType;
764 /* if none of them exist */
765 if (!defParm && !*actParm)
770 if (getenv("DEBUG_SANITY"))
772 fprintf (stderr, "processParms: %s ", defParm->name);
774 /* make sure the type is complete and sane */
775 checkTypeSanity(defParm->etype, defParm->name);
778 if (IS_CODEPTR (func->ftype))
779 functype = func->ftype->next;
781 functype = func->ftype;
783 /* if the function is being called via a pointer & */
784 /* it has not been defined reentrant then we cannot */
785 /* have parameters */
786 /* PIC16 port can... */
787 if (!TARGET_IS_PIC16)
789 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
791 werror (E_NONRENT_ARGS);
797 /* if defined parameters ended but actual parameters */
798 /* exist and this is not defined as a variable arg */
799 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
801 werror (E_TOO_MANY_PARMS);
805 /* if defined parameters present but no actual parameters */
806 if (defParm && !*actParm)
808 werror (E_TOO_FEW_PARMS);
812 /* if this is a PARAM node then match left & right */
813 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
815 (*actParm)->decorated = 1;
816 return (processParms (func, defParm,
817 &(*actParm)->left, parmNumber, FALSE) ||
818 processParms (func, defParm ? defParm->next : NULL,
819 &(*actParm)->right, parmNumber, rightmost));
821 else if (defParm) /* not vararg */
823 /* If we have found a value node by following only right-hand links,
824 * then we know that there are no more values after us.
826 * Therefore, if there are more defined parameters, the caller didn't
829 if (rightmost && defParm->next)
831 werror (E_TOO_FEW_PARMS);
836 /* decorate parameter */
837 resultType = defParm ? getResultTypeFromType (defParm->type) :
839 *actParm = decorateType (*actParm, resultType);
841 if (IS_VOID((*actParm)->ftype))
843 werror (E_VOID_VALUE_USED);
847 /* If this is a varargs function... */
848 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
853 /* don't perform integer promotion of explicitly typecasted variable arguments
854 * if sdcc extensions are enabled */
855 if (options.std_sdcc &&
856 (IS_CAST_OP (*actParm) ||
857 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
858 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
860 /* Parameter was explicitly typecast; don't touch it. */
864 ftype = (*actParm)->ftype;
866 /* If it's a char, upcast to int. */
867 if (IS_INTEGRAL (ftype)
868 && (getSize (ftype) < (unsigned) INTSIZE))
870 newType = newAst_LINK(INTTYPE);
873 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
875 newType = newAst_LINK (copyLinkChain(ftype));
876 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
879 if (IS_AGGREGATE (ftype))
881 newType = newAst_LINK (copyLinkChain (ftype));
882 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887 /* cast required; change this op to a cast. */
888 (*actParm)->decorated = 0;
889 *actParm = newNode (CAST, newType, *actParm);
890 (*actParm)->filename = (*actParm)->right->filename;
891 (*actParm)->lineno = (*actParm)->right->lineno;
893 decorateType (*actParm, RESULT_TYPE_NONE);
898 /* if defined parameters ended but actual has not & */
900 if (!defParm && *actParm &&
901 (options.stackAuto || IFFUNC_ISREENT (functype)))
904 resolveSymbols (*actParm);
906 /* the parameter type must be at least castable */
907 if (compareType (defParm->type, (*actParm)->ftype) == 0)
909 werror (E_INCOMPAT_TYPES);
910 printFromToType ((*actParm)->ftype, defParm->type);
914 /* if the parameter is castable then add the cast */
915 if (compareType (defParm->type, (*actParm)->ftype) < 0)
919 resultType = getResultTypeFromType (defParm->etype);
920 pTree = resolveSymbols (copyAst (*actParm));
922 /* now change the current one to a cast */
923 (*actParm)->type = EX_OP;
924 (*actParm)->opval.op = CAST;
925 (*actParm)->left = newAst_LINK (defParm->type);
926 (*actParm)->right = pTree;
927 (*actParm)->decorated = 0; /* force typechecking */
928 decorateType (*actParm, resultType);
931 /* make a copy and change the regparm type to the defined parm */
932 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
933 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
934 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
936 /* if the function is being called via a pointer & */
937 /* this parameter is not passed in registers */
938 /* then the function must be defined reentrant */
939 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
940 !IFFUNC_ISREENT (functype) && !options.stackAuto)
942 werror (E_NONRENT_ARGS);
951 /*-----------------------------------------------------------------*/
952 /* createIvalType - generates ival for basic types */
953 /*-----------------------------------------------------------------*/
955 createIvalType (ast * sym, sym_link * type, initList * ilist)
959 /* if initList is deep */
960 if (ilist && ilist->type == INIT_DEEP)
961 ilist = ilist->init.deep;
964 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
966 iExpr = newAst_VALUE (valueFromLit (0));
967 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
970 /*-----------------------------------------------------------------*/
971 /* createIvalStruct - generates initial value for structures */
972 /*-----------------------------------------------------------------*/
974 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
980 sym_link * etype = getSpec (type);
982 sflds = SPEC_STRUCT (type)->fields;
983 if (ilist && ilist->type != INIT_DEEP)
985 werror (E_INIT_STRUCT, "");
989 iloop = ilist ? ilist->init.deep : NULL;
991 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
993 /* if we have come to end */
994 if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1000 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
1001 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
1002 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
1003 iloop, rast, rootValue)),
1009 if (IS_AST_VALUE (sym))
1010 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1011 W_EXCESS_INITIALIZERS, "struct",
1012 sym->opval.val->sym->name);
1014 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1020 /*-----------------------------------------------------------------*/
1021 /* createIvalArray - generates code for array initialization */
1022 /*-----------------------------------------------------------------*/
1024 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1028 int lcnt = 0, size = 0;
1029 literalList *literalL;
1030 sym_link * etype = getSpec (type);
1032 /* take care of the special case */
1033 /* array of characters can be init */
1035 if (IS_CHAR (type->next))
1036 if ((rast = createIvalCharPtr (sym,
1038 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1041 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1043 /* not the special case */
1044 if (ilist && ilist->type != INIT_DEEP)
1046 werror (E_INIT_STRUCT, "");
1050 iloop = ilist ? ilist->init.deep : NULL;
1051 lcnt = DCL_ELEM (type);
1054 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1059 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
1063 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1065 rast = newNode(ARRAYINIT, aSym, NULL);
1066 rast->values.constlist = literalL;
1068 // Make sure size is set to length of initializer list.
1072 iloop = iloop->next;
1075 if (lcnt && size > lcnt)
1077 // Array size was specified, and we have more initializers than needed.
1078 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1079 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1089 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1094 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1095 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1096 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1098 iloop = (iloop ? iloop->next : NULL);
1100 /* no of elements given and we */
1101 /* have generated for all of them */
1104 // is this a better way? at least it won't crash
1105 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1106 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1113 /* if we have not been given a size */
1114 if (!DCL_ELEM (type))
1116 /* check, if it's a flexible array */
1117 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1118 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1120 DCL_ELEM (type) = size;
1123 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1127 /*-----------------------------------------------------------------*/
1128 /* createIvalCharPtr - generates initial values for char pointers */
1129 /*-----------------------------------------------------------------*/
1131 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1136 /* if this is a pointer & right is a literal array then */
1137 /* just assignment will do */
1138 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1139 SPEC_SCLS (iexpr->etype) == S_CODE)
1140 && IS_ARRAY (iexpr->ftype)))
1141 return newNode ('=', sym, iexpr);
1143 /* left side is an array so we have to assign each element */
1146 /* for each character generate an assignment */
1147 /* to the array element */
1149 unsigned int symsize = getSize (type);
1151 if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
1154 for (i = 0; i < symsize; ++i)
1156 rast = newNode (NULLOP,
1160 newAst_VALUE (valueFromLit ((float) i))),
1161 newAst_VALUE (valueFromLit (0))));
1164 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1167 if ((IS_LITERAL (iexpr->etype) ||
1168 SPEC_SCLS (iexpr->etype) == S_CODE)
1169 && IS_ARRAY (iexpr->ftype))
1171 /* for each character generate an assignment */
1172 /* to the array element */
1173 char *s = SPEC_CVAL (iexpr->etype).v_char;
1175 unsigned int symsize = getSize (type);
1177 size = getSize (iexpr->ftype);
1178 if (symsize && size > symsize)
1182 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1184 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1190 for (i = 0; i < size; i++)
1192 rast = newNode (NULLOP,
1196 newAst_VALUE (valueFromLit ((float) i))),
1197 newAst_VALUE (valueFromLit (*s++))));
1200 // now WE don't need iexpr's symbol anymore
1201 freeStringSymbol(AST_SYMBOL(iexpr));
1203 /* if we have not been given a size */
1204 if (!DCL_ELEM (type))
1206 /* check, if it's a flexible array */
1207 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1208 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1210 DCL_ELEM (type) = size;
1213 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1219 /*-----------------------------------------------------------------*/
1220 /* createIvalPtr - generates initial value for pointers */
1221 /*-----------------------------------------------------------------*/
1223 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1229 if (ilist && ilist->type == INIT_DEEP)
1230 ilist = ilist->init.deep;
1232 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1234 /* if character pointer */
1235 if (IS_CHAR (type->next))
1236 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1239 return newNode ('=', sym, iexpr);
1242 /*-----------------------------------------------------------------*/
1243 /* createIval - generates code for initial value */
1244 /*-----------------------------------------------------------------*/
1246 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1250 if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
1253 /* if structure then */
1254 if (IS_STRUCT (type))
1255 rast = createIvalStruct (sym, type, ilist, rootValue);
1257 /* if this is a pointer */
1259 rast = createIvalPtr (sym, type, ilist, rootValue);
1261 /* if this is an array */
1262 if (IS_ARRAY (type))
1263 rast = createIvalArray (sym, type, ilist, rootValue);
1265 /* if type is SPECIFIER */
1267 rast = createIvalType (sym, type, ilist);
1270 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1272 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1275 /*-----------------------------------------------------------------*/
1276 /* initAggregates - initialises aggregate variables with initv */
1277 /*-----------------------------------------------------------------*/
1278 ast * initAggregates (symbol * sym, initList * ival, ast * wid)
1280 ast *newAst = newAst_VALUE (symbolVal (sym));
1281 return createIval (newAst, sym->type, ival, wid, newAst);
1284 /*-----------------------------------------------------------------*/
1285 /* gatherAutoInit - creates assignment expressions for initial */
1287 /*-----------------------------------------------------------------*/
1289 gatherAutoInit (symbol * autoChain)
1296 for (sym = autoChain; sym; sym = sym->next)
1298 /* resolve the symbols in the ival */
1300 resolveIvalSym (sym->ival, sym->type);
1303 /* if we are PIC16 port,
1304 * and this is a static,
1305 * and have initial value,
1306 * and not S_CODE, don't emit in gs segment,
1307 * but allow glue.c:pic16emitRegularMap to put symbol
1308 * in idata section */
1309 if(TARGET_IS_PIC16 &&
1310 IS_STATIC (sym->etype) && sym->ival
1311 && SPEC_SCLS(sym->etype) != S_CODE) {
1312 SPEC_SCLS (sym->etype) = S_DATA;
1317 /* if this is a static variable & has an */
1318 /* initial value the code needs to be lifted */
1319 /* here to the main portion since they can be */
1320 /* initialised only once at the start */
1321 if (IS_STATIC (sym->etype) && sym->ival &&
1322 SPEC_SCLS (sym->etype) != S_CODE)
1326 /* insert the symbol into the symbol table */
1327 /* with level = 0 & name = rname */
1328 newSym = copySymbol (sym);
1329 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1331 /* now lift the code to main */
1332 if (IS_AGGREGATE (sym->type)) {
1333 work = initAggregates (sym, sym->ival, NULL);
1335 if (getNelements(sym->type, sym->ival)>1) {
1336 werrorfl (sym->fileDef, sym->lineDef,
1337 W_EXCESS_INITIALIZERS, "scalar",
1340 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1341 list2expr (sym->ival));
1344 setAstFileLine (work, sym->fileDef, sym->lineDef);
1348 staticAutos = newNode (NULLOP, staticAutos, work);
1355 /* if there is an initial value */
1356 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1358 initList *ilist = sym->ival;
1360 while (ilist->type == INIT_DEEP)
1362 ilist = ilist->init.deep;
1365 /* update lineno for error msg */
1366 filename = sym->fileDef;
1367 lineno = sym->lineDef;
1368 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1370 if (IS_AGGREGATE (sym->type))
1372 work = initAggregates (sym, sym->ival, NULL);
1376 if (getNelements(sym->type, sym->ival)>1)
1378 werrorfl (sym->fileDef, sym->lineDef,
1379 W_EXCESS_INITIALIZERS, "scalar",
1382 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1383 list2expr (sym->ival));
1387 setAstFileLine (work, sym->fileDef, sym->lineDef);
1391 init = newNode (NULLOP, init, work);
1400 /*-----------------------------------------------------------------*/
1401 /* freeStringSymbol - delete a literal string if no more usage */
1402 /*-----------------------------------------------------------------*/
1403 void freeStringSymbol(symbol *sym) {
1404 /* make sure this is a literal string */
1405 assert (sym->isstrlit);
1406 if (--sym->isstrlit == 0) { // lower the usage count
1407 memmap *segment=SPEC_OCLS(sym->etype);
1409 deleteSetItem(&segment->syms, sym);
1414 /*-----------------------------------------------------------------*/
1415 /* stringToSymbol - creates a symbol from a literal string */
1416 /*-----------------------------------------------------------------*/
1418 stringToSymbol (value * val)
1420 char name[SDCC_NAME_MAX + 1];
1421 static int charLbl = 0;
1426 // have we heard this before?
1427 for (sp = statsg->syms; sp; sp = sp->next)
1430 size = getSize (sym->type);
1431 if (sym->isstrlit && size == getSize (val->type) &&
1432 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1434 // yes, this is old news. Don't publish it again.
1435 sym->isstrlit++; // but raise the usage count
1436 return symbolVal (sym);
1440 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1441 sym = newSymbol (name, 0); /* make it @ level 0 */
1442 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1444 /* copy the type from the value passed */
1445 sym->type = copyLinkChain (val->type);
1446 sym->etype = getSpec (sym->type);
1447 /* change to storage class & output class */
1448 SPEC_SCLS (sym->etype) = S_CODE;
1449 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1450 SPEC_STAT (sym->etype) = 1;
1451 /* make the level & block = 0 */
1452 sym->block = sym->level = 0;
1454 /* create an ival */
1455 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1460 allocVariables (sym);
1463 return symbolVal (sym);
1467 /*-----------------------------------------------------------------*/
1468 /* processBlockVars - will go thru the ast looking for block if */
1469 /* a block is found then will allocate the syms */
1470 /* will also gather the auto inits present */
1471 /*-----------------------------------------------------------------*/
1473 processBlockVars (ast * tree, int *stack, int action)
1478 /* if this is a block */
1479 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1483 if (action == ALLOCATE)
1485 *stack += allocVariables (tree->values.sym);
1486 autoInit = gatherAutoInit (tree->values.sym);
1488 /* if there are auto inits then do them */
1490 tree->left = newNode (NULLOP, autoInit, tree->left);
1492 else /* action is deallocate */
1493 deallocLocal (tree->values.sym);
1496 processBlockVars (tree->left, stack, action);
1497 processBlockVars (tree->right, stack, action);
1501 /*-------------------------------------------------------------*/
1502 /* constExprTree - returns TRUE if this tree is a constant */
1504 /*-------------------------------------------------------------*/
1505 bool constExprTree (ast *cexpr) {
1511 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1513 switch (cexpr->type)
1516 if (IS_AST_LIT_VALUE(cexpr)) {
1517 // this is a literal
1520 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1521 // a function's address will never change
1524 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1525 // an array's address will never change
1528 if (IS_AST_SYM_VALUE(cexpr) &&
1529 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1530 // a symbol in code space will never change
1531 // This is only for the 'char *s="hallo"' case and will have to leave
1532 //printf(" code space symbol");
1537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1538 "unexpected link in expression tree\n");
1541 if (cexpr->opval.op==ARRAYINIT) {
1542 // this is a list of literals
1545 if (cexpr->opval.op=='=') {
1546 return constExprTree(cexpr->right);
1548 if (cexpr->opval.op==CAST) {
1549 // cast ignored, maybe we should throw a warning here?
1550 return constExprTree(cexpr->right);
1552 if (cexpr->opval.op=='&') {
1555 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1558 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1563 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1568 /*-----------------------------------------------------------------*/
1569 /* constExprValue - returns the value of a constant expression */
1570 /* or NULL if it is not a constant expression */
1571 /*-----------------------------------------------------------------*/
1573 constExprValue (ast * cexpr, int check)
1575 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1577 /* if this is not a constant then */
1578 if (!IS_LITERAL (cexpr->ftype))
1580 /* then check if this is a literal array
1582 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1583 SPEC_CVAL (cexpr->etype).v_char &&
1584 IS_ARRAY (cexpr->ftype))
1586 value *val = valFromType (cexpr->ftype);
1587 SPEC_SCLS (val->etype) = S_LITERAL;
1588 val->sym = cexpr->opval.val->sym;
1589 val->sym->type = copyLinkChain (cexpr->ftype);
1590 val->sym->etype = getSpec (val->sym->type);
1591 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1595 /* if we are casting a literal value then */
1596 if (IS_AST_OP (cexpr) &&
1597 cexpr->opval.op == CAST &&
1598 IS_LITERAL (cexpr->right->ftype))
1600 return valCastLiteral (cexpr->ftype,
1601 floatFromVal (cexpr->right->opval.val));
1604 if (IS_AST_VALUE (cexpr))
1606 return cexpr->opval.val;
1610 werror (E_CONST_EXPECTED, "found expression");
1615 /* return the value */
1616 if (IS_AST_VALUE (cexpr))
1618 return cexpr->opval.val;
1623 /*-----------------------------------------------------------------*/
1624 /* isLabelInAst - will return true if a given label is found */
1625 /*-----------------------------------------------------------------*/
1627 isLabelInAst (symbol * label, ast * tree)
1629 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1632 if (IS_AST_OP (tree) &&
1633 tree->opval.op == LABEL &&
1634 isSymbolEqual (AST_SYMBOL (tree->left), label))
1637 return isLabelInAst (label, tree->right) &&
1638 isLabelInAst (label, tree->left);
1641 /*-----------------------------------------------------------------*/
1642 /* isLoopCountable - return true if the loop count can be determi- */
1643 /* -ned at compile time . */
1644 /*-----------------------------------------------------------------*/
1646 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1647 symbol ** sym, ast ** init, ast ** end)
1650 /* the loop is considered countable if the following
1651 conditions are true :-
1653 a) initExpr :- <sym> = <const>
1654 b) condExpr :- <sym> < <const1>
1655 c) loopExpr :- <sym> ++
1658 /* first check the initExpr */
1659 if (IS_AST_OP (initExpr) &&
1660 initExpr->opval.op == '=' && /* is assignment */
1661 IS_AST_SYM_VALUE (initExpr->left))
1662 { /* left is a symbol */
1664 *sym = AST_SYMBOL (initExpr->left);
1665 *init = initExpr->right;
1670 /* don't reverse loop with volatile counter */
1671 if (IS_VOLATILE ((*sym)->type))
1674 /* for now the symbol has to be of
1676 if (!IS_INTEGRAL ((*sym)->type))
1679 /* now check condExpr */
1680 if (IS_AST_OP (condExpr))
1683 switch (condExpr->opval.op)
1686 if (IS_AST_SYM_VALUE (condExpr->left) &&
1687 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1688 IS_AST_LIT_VALUE (condExpr->right))
1690 *end = condExpr->right;
1696 if (IS_AST_OP (condExpr->left) &&
1697 condExpr->left->opval.op == '>' &&
1698 IS_AST_LIT_VALUE (condExpr->left->right) &&
1699 IS_AST_SYM_VALUE (condExpr->left->left) &&
1700 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1703 *end = newNode ('+', condExpr->left->right,
1704 newAst_VALUE (constCharVal (1)));
1717 /* check loop expression is of the form <sym>++ */
1718 if (!IS_AST_OP (loopExpr))
1721 /* check if <sym> ++ */
1722 if (loopExpr->opval.op == INC_OP)
1728 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1729 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1736 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1737 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1745 if (loopExpr->opval.op == ADD_ASSIGN)
1748 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1749 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1750 IS_AST_LIT_VALUE (loopExpr->right) &&
1751 AST_ULONG_VALUE (loopExpr->right) != 1)
1759 /*-----------------------------------------------------------------*/
1760 /* astHasVolatile - returns true if ast contains any volatile */
1761 /*-----------------------------------------------------------------*/
1763 astHasVolatile (ast * tree)
1768 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1771 if (IS_AST_OP (tree))
1772 return astHasVolatile (tree->left) ||
1773 astHasVolatile (tree->right);
1778 /*-----------------------------------------------------------------*/
1779 /* astHasPointer - return true if the ast contains any ptr variable */
1780 /*-----------------------------------------------------------------*/
1782 astHasPointer (ast * tree)
1787 if (IS_AST_LINK (tree))
1790 /* if we hit an array expression then check
1791 only the left side */
1792 if (IS_AST_OP (tree) && tree->opval.op == '[')
1793 return astHasPointer (tree->left);
1795 if (IS_AST_VALUE (tree))
1796 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1798 return astHasPointer (tree->left) ||
1799 astHasPointer (tree->right);
1803 /*-----------------------------------------------------------------*/
1804 /* astHasSymbol - return true if the ast has the given symbol */
1805 /*-----------------------------------------------------------------*/
1807 astHasSymbol (ast * tree, symbol * sym)
1809 if (!tree || IS_AST_LINK (tree))
1812 if (IS_AST_VALUE (tree))
1814 if (IS_AST_SYM_VALUE (tree))
1815 return isSymbolEqual (AST_SYMBOL (tree), sym);
1820 return astHasSymbol (tree->left, sym) ||
1821 astHasSymbol (tree->right, sym);
1824 /*-----------------------------------------------------------------*/
1825 /* astHasDeref - return true if the ast has an indirect access */
1826 /*-----------------------------------------------------------------*/
1828 astHasDeref (ast * tree)
1830 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1833 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1835 return astHasDeref (tree->left) || astHasDeref (tree->right);
1838 /*-----------------------------------------------------------------*/
1839 /* isConformingBody - the loop body has to conform to a set of */
1840 /* rules for the loop to be considered reversible read on for rules*/
1841 /*-----------------------------------------------------------------*/
1843 isConformingBody (ast * pbody, symbol * sym, ast * body)
1846 /* we are going to do a pre-order traversal of the
1847 tree && check for the following conditions. (essentially
1848 a set of very shallow tests )
1849 a) the sym passed does not participate in any arithmetic operation
1850 b) There are no function calls
1851 c) all jumps are within the body
1852 d) address of loop control variable not taken
1853 e) if an assignment has a pointer on the left hand side make sure
1854 right does not have loop control variable
1857 /* if we reach the end or a leaf then true */
1858 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1861 /* if anything else is "volatile" */
1862 if (IS_VOLATILE (TETYPE (pbody)))
1865 /* we will walk the body in a pre-order traversal for
1867 switch (pbody->opval.op)
1869 /*------------------------------------------------------------------*/
1871 // if the loopvar is used as an index
1872 /* array op is commutative -- must check both left & right */
1873 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1876 return isConformingBody (pbody->right, sym, body)
1877 && isConformingBody (pbody->left, sym, body);
1879 /*------------------------------------------------------------------*/
1884 /*------------------------------------------------------------------*/
1888 /* sure we are not sym is not modified */
1890 IS_AST_SYM_VALUE (pbody->left) &&
1891 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1895 IS_AST_SYM_VALUE (pbody->right) &&
1896 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1901 /*------------------------------------------------------------------*/
1903 case '*': /* can be unary : if right is null then unary operation */
1908 /* if right is NULL then unary operation */
1909 /*------------------------------------------------------------------*/
1910 /*----------------------------*/
1912 /*----------------------------*/
1915 if (IS_AST_SYM_VALUE (pbody->left) &&
1916 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1919 return isConformingBody (pbody->left, sym, body);
1923 if (astHasSymbol (pbody->left, sym) ||
1924 astHasSymbol (pbody->right, sym))
1929 /*------------------------------------------------------------------*/
1940 if (IS_AST_SYM_VALUE (pbody->left) &&
1941 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1944 if (IS_AST_SYM_VALUE (pbody->right) &&
1945 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1948 return isConformingBody (pbody->left, sym, body) &&
1949 isConformingBody (pbody->right, sym, body);
1957 if (IS_AST_SYM_VALUE (pbody->left) &&
1958 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1960 return isConformingBody (pbody->left, sym, body);
1962 /*------------------------------------------------------------------*/
1974 case SIZEOF: /* evaluate wihout code generation */
1976 if (IS_AST_SYM_VALUE (pbody->left) &&
1977 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1980 if (IS_AST_SYM_VALUE (pbody->right) &&
1981 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1984 return isConformingBody (pbody->left, sym, body) &&
1985 isConformingBody (pbody->right, sym, body);
1987 /*------------------------------------------------------------------*/
1990 /* if left has a pointer & right has loop
1991 control variable then we cannot */
1992 if (astHasPointer (pbody->left) &&
1993 astHasSymbol (pbody->right, sym))
1995 if (astHasVolatile (pbody->left))
1998 if (IS_AST_SYM_VALUE (pbody->left)) {
1999 // if the loopvar has an assignment
2000 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
2002 // if the loopvar is used in another (maybe conditional) block
2003 if (astHasSymbol (pbody->right, sym) &&
2004 (pbody->level >= body->level)) {
2009 if (astHasVolatile (pbody->left))
2012 if (astHasDeref(pbody->right))
2015 return isConformingBody (pbody->left, sym, body) &&
2016 isConformingBody (pbody->right, sym, body);
2027 assert ("Parser should not have generated this\n");
2029 /*------------------------------------------------------------------*/
2030 /*----------------------------*/
2031 /* comma operator */
2032 /*----------------------------*/
2034 return isConformingBody (pbody->left, sym, body) &&
2035 isConformingBody (pbody->right, sym, body);
2037 /*------------------------------------------------------------------*/
2038 /*----------------------------*/
2040 /*----------------------------*/
2042 /* if local & not passed as parameter &
2043 not used to find the function then ok */
2044 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2045 !astHasSymbol (pbody->left, sym))
2051 /*------------------------------------------------------------------*/
2052 /*----------------------------*/
2053 /* return statement */
2054 /*----------------------------*/
2059 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2064 if (astHasSymbol (pbody->left, sym))
2071 return isConformingBody (pbody->left, sym, body) &&
2072 isConformingBody (pbody->right, sym, body);
2075 /*-----------------------------------------------------------------*/
2076 /* isLoopReversible - takes a for loop as input && returns true */
2077 /* if the for loop is reversible. If yes will set the value of */
2078 /* the loop control var & init value & termination value */
2079 /*-----------------------------------------------------------------*/
2081 isLoopReversible (ast * loop, symbol ** loopCntrl,
2082 ast ** init, ast ** end)
2084 /* if option says don't do it then don't */
2085 if (optimize.noLoopReverse)
2087 /* there are several tests to determine this */
2089 /* for loop has to be of the form
2090 for ( <sym> = <const1> ;
2091 [<sym> < <const2>] ;
2092 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2094 if (!isLoopCountable (AST_FOR (loop, initExpr),
2095 AST_FOR (loop, condExpr),
2096 AST_FOR (loop, loopExpr),
2097 loopCntrl, init, end))
2100 /* now do some serious checking on the body of the loop
2103 return isConformingBody (loop->left, *loopCntrl, loop->left);
2107 /*-----------------------------------------------------------------*/
2108 /* replLoopSym - replace the loop sym by loop sym -1 */
2109 /*-----------------------------------------------------------------*/
2111 replLoopSym (ast * body, symbol * sym)
2114 if (!body || IS_AST_LINK (body))
2117 if (IS_AST_SYM_VALUE (body))
2120 if (isSymbolEqual (AST_SYMBOL (body), sym))
2124 body->opval.op = '-';
2125 body->left = newAst_VALUE (symbolVal (sym));
2126 body->right = newAst_VALUE (constCharVal (1));
2134 replLoopSym (body->left, sym);
2135 replLoopSym (body->right, sym);
2139 /*-----------------------------------------------------------------*/
2140 /* reverseLoop - do the actual loop reversal */
2141 /*-----------------------------------------------------------------*/
2143 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2147 /* create the following tree
2152 if (sym) goto for_continue ;
2155 /* put it together piece by piece */
2156 rloop = newNode (NULLOP,
2157 createIf (newAst_VALUE (symbolVal (sym)),
2159 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2162 newAst_VALUE (symbolVal (sym)),
2165 replLoopSym (loop->left, sym);
2166 setAstFileLine (rloop, init->filename, init->lineno);
2168 rloop = newNode (NULLOP,
2170 newAst_VALUE (symbolVal (sym)),
2171 newNode ('-', end, init)),
2172 createLabel (AST_FOR (loop, continueLabel),
2176 newNode (SUB_ASSIGN,
2177 newAst_VALUE (symbolVal (sym)),
2178 newAst_VALUE (constCharVal (1))),
2181 rloop->lineno=init->lineno;
2182 return decorateType (rloop, RESULT_TYPE_NONE);
2186 /*-----------------------------------------------------------------*/
2187 /* searchLitOp - search tree (*ops only) for an ast with literal */
2188 /*-----------------------------------------------------------------*/
2190 searchLitOp (ast *tree, ast **parent, const char *ops)
2194 if (tree && optimize.global_cse)
2196 /* is there a literal operand? */
2198 IS_AST_OP(tree->right) &&
2199 tree->right->right &&
2200 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2202 if (IS_LITERAL (RTYPE (tree->right)) !=
2203 IS_LITERAL (LTYPE (tree->right)))
2205 tree->right->decorated = 0;
2206 tree->decorated = 0;
2210 ret = searchLitOp (tree->right, parent, ops);
2215 IS_AST_OP(tree->left) &&
2216 tree->left->right &&
2217 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2219 if (IS_LITERAL (RTYPE (tree->left)) !=
2220 IS_LITERAL (LTYPE (tree->left)))
2222 tree->left->decorated = 0;
2223 tree->decorated = 0;
2227 ret = searchLitOp (tree->left, parent, ops);
2235 /*-----------------------------------------------------------------*/
2236 /* getResultFromType */
2237 /*-----------------------------------------------------------------*/
2239 getResultTypeFromType (sym_link *type)
2241 /* type = getSpec (type); */
2243 return RESULT_TYPE_BIT;
2244 if (IS_BITFIELD (type))
2246 int blen = SPEC_BLEN (type);
2249 return RESULT_TYPE_BIT;
2251 return RESULT_TYPE_CHAR;
2252 return RESULT_TYPE_INT;
2255 return RESULT_TYPE_CHAR;
2256 if (IS_INT (type) && !IS_LONG (type))
2257 return RESULT_TYPE_INT;
2258 return RESULT_TYPE_OTHER;
2261 /*-----------------------------------------------------------------*/
2262 /* addCast - adds casts to a type specified by RESULT_TYPE */
2263 /*-----------------------------------------------------------------*/
2265 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2268 bool upCasted = FALSE;
2272 case RESULT_TYPE_NONE:
2273 /* if thing smaller than int must be promoted to int */
2275 getSize (tree->etype) >= INTSIZE)
2276 /* promotion not necessary or already an int */
2278 /* char and bits: promote to int */
2279 newLink = newIntLink();
2282 case RESULT_TYPE_BIT:
2284 /* already an int */
2285 bitsForType (tree->etype) >= 16 ||
2286 /* bit to bit operation: don't promote, the code generators
2287 hopefully know everything about promotion rules */
2288 bitsForType (tree->etype) == 1)
2290 newLink = newIntLink();
2293 case RESULT_TYPE_CHAR:
2294 if (IS_CHAR (tree->etype) ||
2295 IS_FLOAT(tree->etype) ||
2296 IS_FIXED(tree->etype))
2298 newLink = newCharLink();
2300 case RESULT_TYPE_INT:
2302 if (getSize (tree->etype) > INTSIZE)
2304 /* warn ("Loosing significant digits"); */
2308 /* char: promote to int */
2310 getSize (tree->etype) >= INTSIZE)
2312 newLink = newIntLink();
2315 case RESULT_TYPE_IFX:
2316 case RESULT_TYPE_OTHER:
2318 /* return type is ifx, long, float: promote char to int */
2319 getSize (tree->etype) >= INTSIZE)
2321 newLink = newIntLink();
2327 tree->decorated = 0;
2328 tree = newNode (CAST, newAst_LINK (newLink), tree);
2329 tree->filename = tree->right->filename;
2330 tree->lineno = tree->right->lineno;
2331 /* keep unsigned type during cast to smaller type,
2332 but not when promoting from char to int */
2334 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2335 return decorateType (tree, resultType);
2338 /*-----------------------------------------------------------------*/
2339 /* resultTypePropagate - decides if resultType can be propagated */
2340 /*-----------------------------------------------------------------*/
2342 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2344 switch (tree->opval.op)
2361 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2362 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2363 return RESULT_TYPE_NONE;
2368 return RESULT_TYPE_NONE;
2372 return RESULT_TYPE_IFX;
2374 return RESULT_TYPE_NONE;
2378 /*-----------------------------------------------------------------*/
2379 /* getLeftResultType - gets type from left branch for propagation */
2380 /*-----------------------------------------------------------------*/
2382 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2384 switch (tree->opval.op)
2388 if (IS_PTR (LTYPE (tree)))
2389 return RESULT_TYPE_NONE;
2391 return getResultTypeFromType (LETYPE (tree));
2393 if (IS_PTR (currFunc->type->next))
2394 return RESULT_TYPE_NONE;
2396 return getResultTypeFromType (currFunc->type->next);
2398 if (!IS_ARRAY (LTYPE (tree)))
2400 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2401 return RESULT_TYPE_CHAR;
2408 /*------------------------------------------------------------------*/
2409 /* gatherImplicitVariables: assigns correct type information to */
2410 /* symbols and values created by replaceAstWithTemporary */
2411 /* and adds the symbols to the declarations list of the */
2412 /* innermost block that contains them */
2413 /*------------------------------------------------------------------*/
2415 gatherImplicitVariables (ast * tree, ast * block)
2420 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2422 /* keep track of containing scope */
2425 if (tree->type == EX_OP && tree->opval.op == '=' &&
2426 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2428 symbol *assignee = tree->left->opval.val->sym;
2430 /* special case for assignment to compiler-generated temporary variable:
2431 compute type of RHS, and set the symbol's type to match */
2432 if (assignee->type == NULL && assignee->infertype) {
2433 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2435 if (dtr != tree->right)
2438 assignee->type = copyLinkChain(TTYPE(dtr));
2439 assignee->etype = getSpec(assignee->type);
2440 SPEC_SCLS (assignee->etype) = S_AUTO;
2441 SPEC_OCLS (assignee->etype) = NULL;
2442 SPEC_EXTR (assignee->etype) = 0;
2443 SPEC_STAT (assignee->etype) = 0;
2444 SPEC_VOLATILE (assignee->etype) = 0;
2445 SPEC_ABSA (assignee->etype) = 0;
2447 wassertl(block != NULL, "implicit variable not contained in block");
2448 wassert(assignee->next == NULL);
2449 if (block != NULL) {
2450 symbol **decl = &(block->values.sym);
2453 wassert(*decl != assignee); /* should not already be in list */
2454 decl = &( (*decl)->next );
2461 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2462 tree->opval.val->type == NULL &&
2463 tree->opval.val->sym &&
2464 tree->opval.val->sym->infertype)
2466 /* fixup type of value for compiler-inferred temporary var */
2467 tree->opval.val->type = tree->opval.val->sym->type;
2468 tree->opval.val->etype = tree->opval.val->sym->etype;
2471 gatherImplicitVariables(tree->left, block);
2472 gatherImplicitVariables(tree->right, block);
2475 /*--------------------------------------------------------------------*/
2476 /* decorateType - compute type for this tree, also does type checking.*/
2477 /* This is done bottom up, since type has to flow upwards. */
2478 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2479 /* result is a char and the operand(s) are int's. */
2480 /* It also does constant folding, and parameter checking. */
2481 /*--------------------------------------------------------------------*/
2483 decorateType (ast * tree, RESULT_TYPE resultType)
2487 RESULT_TYPE resultTypeProp;
2492 /* if already has type then do nothing */
2493 if (tree->decorated)
2496 tree->decorated = 1;
2499 /* print the line */
2500 /* if not block & function */
2501 if (tree->type == EX_OP &&
2502 (tree->opval.op != FUNCTION &&
2503 tree->opval.op != BLOCK &&
2504 tree->opval.op != NULLOP))
2506 filename = tree->filename;
2507 lineno = tree->lineno;
2511 /* if any child is an error | this one is an error do nothing */
2512 if (tree->isError ||
2513 (tree->left && tree->left->isError) ||
2514 (tree->right && tree->right->isError))
2517 /*------------------------------------------------------------------*/
2518 /*----------------------------*/
2519 /* leaf has been reached */
2520 /*----------------------------*/
2521 filename = tree->filename;
2522 lineno = tree->lineno;
2523 /* if this is of type value */
2524 /* just get the type */
2525 if (tree->type == EX_VALUE)
2527 if (IS_LITERAL (tree->opval.val->etype))
2529 /* if this is a character array then declare it */
2530 if (IS_ARRAY (tree->opval.val->type))
2531 tree->opval.val = stringToSymbol (tree->opval.val);
2533 /* otherwise just copy the type information */
2534 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2538 if (tree->opval.val->sym)
2540 /* if the undefined flag is set then give error message */
2541 if (tree->opval.val->sym->undefined)
2543 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2545 TTYPE (tree) = TETYPE (tree) =
2546 tree->opval.val->type = tree->opval.val->sym->type =
2547 tree->opval.val->etype = tree->opval.val->sym->etype =
2548 copyLinkChain (INTTYPE);
2550 else if (tree->opval.val->sym->implicit)
2552 /* if implicit i.e. struct/union member then no type */
2553 TTYPE (tree) = TETYPE (tree) = NULL;
2557 /* copy the type from the value into the ast */
2558 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2560 /* and mark the symbol as referenced */
2561 tree->opval.val->sym->isref = 1;
2565 wassert(0); /* unreached: all values are literals or symbols */
2570 /* if type link for the case of cast */
2571 if (tree->type == EX_LINK)
2573 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2581 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2583 if (tree->left && tree->left->type == EX_OPERAND
2584 && (tree->left->opval.op == INC_OP
2585 || tree->left->opval.op == DEC_OP)
2586 && tree->left->left)
2588 tree->left->right = tree->left->left;
2589 tree->left->left = NULL;
2591 if (tree->right && tree->right->type == EX_OPERAND
2592 && (tree->right->opval.op == INC_OP
2593 || tree->right->opval.op == DEC_OP)
2594 && tree->right->left)
2596 tree->right->right = tree->right->left;
2597 tree->right->left = NULL;
2602 /* Before decorating the left branch we've to decide in dependence
2603 upon tree->opval.op, if resultType can be propagated */
2604 resultTypeProp = resultTypePropagate (tree, resultType);
2606 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2607 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2609 dtl = decorateType (tree->left, resultTypeProp);
2611 /* if an array node, we may need to swap branches */
2612 if (tree->opval.op == '[')
2614 /* determine which is the array & which the index */
2615 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2616 IS_INTEGRAL (LTYPE (tree)))
2618 ast *tempTree = tree->left;
2619 tree->left = tree->right;
2620 tree->right = tempTree;
2624 /* After decorating the left branch there's type information available
2625 in tree->left->?type. If the op is e.g. '=' we extract the type
2626 information from there and propagate it to the right branch. */
2627 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2629 switch (tree->opval.op)
2632 /* delay right side for '?' operator since conditional macro
2633 expansions might rely on this */
2637 /* decorate right side for CALL (parameter list) in processParms();
2638 there is resultType available */
2642 /* don't allocate string if it is a sizeof argument */
2644 dtr = decorateType (tree->right, resultTypeProp);
2648 dtr = decorateType (tree->right, resultTypeProp);
2652 /* this is to take care of situations
2653 when the tree gets rewritten */
2654 if (dtl != tree->left)
2656 if (dtr != tree->right)
2658 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2662 /* depending on type of operator do */
2664 switch (tree->opval.op)
2666 /*------------------------------------------------------------------*/
2667 /*----------------------------*/
2669 /*----------------------------*/
2672 /* first check if this is a array or a pointer */
2673 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2675 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2676 goto errorTreeReturn;
2679 /* check if the type of the idx */
2680 if (!IS_INTEGRAL (RTYPE (tree)))
2682 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2683 goto errorTreeReturn;
2686 /* if the left is an rvalue then error */
2689 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2690 goto errorTreeReturn;
2693 if (IS_LITERAL (RTYPE (tree)))
2695 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2696 int arraySize = DCL_ELEM (LTYPE (tree));
2697 if (arraySize && arrayIndex >= arraySize)
2699 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2704 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2705 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2708 /*------------------------------------------------------------------*/
2709 /*----------------------------*/
2711 /*----------------------------*/
2713 /* if this is not a structure */
2714 if (!IS_STRUCT (LTYPE (tree)))
2716 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2717 goto errorTreeReturn;
2719 TTYPE (tree) = structElemType (LTYPE (tree),
2720 (tree->right->type == EX_VALUE ?
2721 tree->right->opval.val : NULL));
2722 TETYPE (tree) = getSpec (TTYPE (tree));
2725 /*------------------------------------------------------------------*/
2726 /*----------------------------*/
2727 /* struct/union pointer */
2728 /*----------------------------*/
2730 /* if not pointer to a structure */
2731 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2733 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2734 goto errorTreeReturn;
2737 if (!IS_STRUCT (LTYPE (tree)->next))
2739 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2740 goto errorTreeReturn;
2743 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2744 (tree->right->type == EX_VALUE ?
2745 tree->right->opval.val : NULL));
2746 TETYPE (tree) = getSpec (TTYPE (tree));
2748 /* adjust the storage class */
2749 switch (DCL_TYPE(tree->left->ftype)) {
2751 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2754 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2757 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2760 SPEC_SCLS (TETYPE (tree)) = 0;
2763 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2766 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2769 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2772 SPEC_SCLS (TETYPE (tree)) = 0;
2779 /* This breaks with extern declarations, bitfields, and perhaps other */
2780 /* cases (gcse). Let's leave this optimization disabled for now and */
2781 /* ponder if there's a safe way to do this. -- EEP */
2783 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2784 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2786 /* If defined struct type at addr var
2787 then rewrite (&struct var)->member
2789 and define membertype at (addr+offsetof(struct var,member)) temp
2792 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2793 AST_SYMBOL(tree->right));
2795 sym = newSymbol(genSymName (0), 0);
2796 sym->type = TTYPE (tree);
2797 sym->etype = getSpec(sym->type);
2798 sym->lineDef = tree->lineno;
2801 SPEC_STAT (sym->etype) = 1;
2802 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2804 SPEC_ABSA(sym->etype) = 1;
2805 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2808 AST_VALUE (tree) = symbolVal(sym);
2811 tree->type = EX_VALUE;
2819 /*------------------------------------------------------------------*/
2820 /*----------------------------*/
2821 /* ++/-- operation */
2822 /*----------------------------*/
2826 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2827 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2828 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2829 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2838 /*------------------------------------------------------------------*/
2839 /*----------------------------*/
2841 /*----------------------------*/
2842 case '&': /* can be unary */
2843 /* if right is NULL then unary operation */
2844 if (tree->right) /* not an unary operation */
2847 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2849 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2850 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2851 printTypeChain (LTYPE (tree), stderr);
2852 fprintf (stderr, ",");
2853 printTypeChain (RTYPE (tree), stderr);
2854 fprintf (stderr, "\n");
2855 goto errorTreeReturn;
2858 /* if they are both literal */
2859 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2861 tree->type = EX_VALUE;
2862 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2863 valFromType (RETYPE (tree)), '&');
2865 tree->right = tree->left = NULL;
2866 TETYPE (tree) = tree->opval.val->etype;
2867 TTYPE (tree) = tree->opval.val->type;
2871 /* see if this is a GETHBIT operation if yes
2874 ast *otree = optimizeGetHbit (tree, resultType);
2877 return decorateType (otree, RESULT_TYPE_NONE);
2880 /* see if this is a GETABIT operation if yes
2883 ast *otree = optimizeGetAbit (tree, resultType);
2886 return decorateType (otree, RESULT_TYPE_NONE);
2889 /* see if this is a GETBYTE operation if yes
2892 ast *otree = optimizeGetByte (tree, resultType);
2895 return decorateType (otree, RESULT_TYPE_NONE);
2898 /* see if this is a GETWORD operation if yes
2901 ast *otree = optimizeGetWord (tree, resultType);
2904 return decorateType (otree, RESULT_TYPE_NONE);
2907 /* if left is a literal exchange left & right */
2908 if (IS_LITERAL (LTYPE (tree)))
2910 ast *tTree = tree->left;
2911 tree->left = tree->right;
2912 tree->right = tTree;
2915 /* if right is a literal and */
2916 /* we can find a 2nd literal in an and-tree then */
2917 /* rearrange the tree */
2918 if (IS_LITERAL (RTYPE (tree)))
2921 ast *litTree = searchLitOp (tree, &parent, "&");
2925 ast *tTree = litTree->left;
2926 litTree->left = tree->right;
2927 tree->right = tTree;
2928 /* both operands in litTree are literal now */
2929 decorateType (parent, resultType);
2933 LRVAL (tree) = RRVAL (tree) = 1;
2935 TTYPE (tree) = computeType (LTYPE (tree),
2939 TETYPE (tree) = getSpec (TTYPE (tree));
2944 /*------------------------------------------------------------------*/
2945 /*----------------------------*/
2947 /*----------------------------*/
2948 p = newLink (DECLARATOR);
2949 /* if bit field then error */
2950 if (IS_BITVAR (tree->left->etype))
2952 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2953 goto errorTreeReturn;
2956 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2958 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2959 goto errorTreeReturn;
2962 if (IS_FUNC (LTYPE (tree)))
2964 // this ought to be ignored
2965 return (tree->left);
2968 if (IS_LITERAL(LTYPE(tree)))
2970 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2971 goto errorTreeReturn;
2976 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2977 goto errorTreeReturn;
2980 DCL_TYPE (p) = POINTER;
2981 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2982 DCL_TYPE (p) = CPOINTER;
2983 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2984 DCL_TYPE (p) = FPOINTER;
2985 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2986 DCL_TYPE (p) = PPOINTER;
2987 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2988 DCL_TYPE (p) = IPOINTER;
2989 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2990 DCL_TYPE (p) = EEPPOINTER;
2991 else if (SPEC_OCLS(tree->left->etype))
2992 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2994 DCL_TYPE (p) = POINTER;
2996 if (IS_AST_SYM_VALUE (tree->left))
2998 AST_SYMBOL (tree->left)->addrtaken = 1;
2999 AST_SYMBOL (tree->left)->allocreq = 1;
3002 p->next = LTYPE (tree);
3004 TETYPE (tree) = getSpec (TTYPE (tree));
3009 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
3010 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
3012 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
3013 AST_SYMBOL(tree->left->right));
3014 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
3015 valueFromLit(element->offset));
3018 tree->type = EX_VALUE;
3019 tree->values.literalFromCast = 1;
3025 /*------------------------------------------------------------------*/
3026 /*----------------------------*/
3028 /*----------------------------*/
3030 /* if the rewrite succeeds then don't go any further */
3032 ast *wtree = optimizeRRCRLC (tree);
3034 return decorateType (wtree, RESULT_TYPE_NONE);
3036 wtree = optimizeSWAP (tree);
3038 return decorateType (wtree, RESULT_TYPE_NONE);
3041 /* if left is a literal exchange left & right */
3042 if (IS_LITERAL (LTYPE (tree)))
3044 ast *tTree = tree->left;
3045 tree->left = tree->right;
3046 tree->right = tTree;
3049 /* if right is a literal and */
3050 /* we can find a 2nd literal in an or-tree then */
3051 /* rearrange the tree */
3052 if (IS_LITERAL (RTYPE (tree)))
3055 ast *litTree = searchLitOp (tree, &parent, "|");
3059 ast *tTree = litTree->left;
3060 litTree->left = tree->right;
3061 tree->right = tTree;
3062 /* both operands in tTree are literal now */
3063 decorateType (parent, resultType);
3068 /*------------------------------------------------------------------*/
3069 /*----------------------------*/
3071 /*----------------------------*/
3073 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3075 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3076 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3077 printTypeChain (LTYPE (tree), stderr);
3078 fprintf (stderr, ",");
3079 printTypeChain (RTYPE (tree), stderr);
3080 fprintf (stderr, "\n");
3081 goto errorTreeReturn;
3084 /* if they are both literal then rewrite the tree */
3085 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3087 tree->type = EX_VALUE;
3088 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3089 valFromType (RETYPE (tree)),
3091 tree->right = tree->left = NULL;
3092 TETYPE (tree) = tree->opval.val->etype;
3093 TTYPE (tree) = tree->opval.val->type;
3097 /* if left is a literal exchange left & right */
3098 if (IS_LITERAL (LTYPE (tree)))
3100 ast *tTree = tree->left;
3101 tree->left = tree->right;
3102 tree->right = tTree;
3105 /* if right is a literal and */
3106 /* we can find a 2nd literal in a xor-tree then */
3107 /* rearrange the tree */
3108 if (IS_LITERAL (RTYPE (tree)) &&
3109 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3112 ast *litTree = searchLitOp (tree, &parent, "^");
3116 ast *tTree = litTree->left;
3117 litTree->left = tree->right;
3118 tree->right = tTree;
3119 /* both operands in litTree are literal now */
3120 decorateType (parent, resultType);
3124 LRVAL (tree) = RRVAL (tree) = 1;
3126 TTYPE (tree) = computeType (LTYPE (tree),
3130 TETYPE (tree) = getSpec (TTYPE (tree));
3134 /*------------------------------------------------------------------*/
3135 /*----------------------------*/
3137 /*----------------------------*/
3139 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3141 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3142 goto errorTreeReturn;
3144 /* if they are both literal then */
3145 /* rewrite the tree */
3146 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3148 tree->type = EX_VALUE;
3149 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3150 valFromType (RETYPE (tree)));
3151 tree->right = tree->left = NULL;
3152 TETYPE (tree) = getSpec (TTYPE (tree) =
3153 tree->opval.val->type);
3157 LRVAL (tree) = RRVAL (tree) = 1;
3159 TETYPE (tree) = getSpec (TTYPE (tree) =
3160 computeType (LTYPE (tree),
3165 /* if right is a literal and */
3166 /* left is also a division by a literal then */
3167 /* rearrange the tree */
3168 if (IS_LITERAL (RTYPE (tree))
3169 /* avoid infinite loop */
3170 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3173 ast *litTree = searchLitOp (tree, &parent, "/");
3176 if (IS_LITERAL (RTYPE (litTree)))
3180 litTree->right = newNode ('*',
3182 copyAst (tree->right));
3183 litTree->right->filename = tree->filename;
3184 litTree->right->lineno = tree->lineno;
3186 tree->right->opval.val = constCharVal (1);
3187 decorateType (parent, resultType);
3191 /* litTree->left is literal: no gcse possible.
3192 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3193 this would cause an infinit loop. */
3194 parent->decorated = 1;
3195 decorateType (litTree, resultType);
3202 /*------------------------------------------------------------------*/
3203 /*----------------------------*/
3205 /*----------------------------*/
3207 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3209 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3210 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3211 printTypeChain (LTYPE (tree), stderr);
3212 fprintf (stderr, ",");
3213 printTypeChain (RTYPE (tree), stderr);
3214 fprintf (stderr, "\n");
3215 goto errorTreeReturn;
3217 /* if they are both literal then */
3218 /* rewrite the tree */
3219 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3221 tree->type = EX_VALUE;
3222 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3223 valFromType (RETYPE (tree)));
3224 tree->right = tree->left = NULL;
3225 TETYPE (tree) = getSpec (TTYPE (tree) =
3226 tree->opval.val->type);
3229 LRVAL (tree) = RRVAL (tree) = 1;
3230 TETYPE (tree) = getSpec (TTYPE (tree) =
3231 computeType (LTYPE (tree),
3237 /*------------------------------------------------------------------*/
3238 /*----------------------------*/
3239 /* address dereference */
3240 /*----------------------------*/
3241 case '*': /* can be unary : if right is null then unary operation */
3244 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3246 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3247 goto errorTreeReturn;
3252 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3253 goto errorTreeReturn;
3255 if (IS_ADDRESS_OF_OP(tree->left))
3257 /* replace *&obj with obj */
3258 return tree->left->left;
3260 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3261 TETYPE (tree) = getSpec (TTYPE (tree));
3262 /* adjust the storage class */
3263 switch (DCL_TYPE(tree->left->ftype)) {
3265 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3268 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3271 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3274 SPEC_SCLS (TETYPE (tree)) = 0;
3277 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3280 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3283 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3286 SPEC_SCLS (TETYPE (tree)) = 0;
3295 /*------------------------------------------------------------------*/
3296 /*----------------------------*/
3297 /* multiplication */
3298 /*----------------------------*/
3299 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3301 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3302 goto errorTreeReturn;
3305 /* if they are both literal then */
3306 /* rewrite the tree */
3307 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3309 tree->type = EX_VALUE;
3310 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3311 valFromType (RETYPE (tree)));
3312 tree->right = tree->left = NULL;
3313 TETYPE (tree) = getSpec (TTYPE (tree) =
3314 tree->opval.val->type);
3318 /* if left is a literal exchange left & right */
3319 if (IS_LITERAL (LTYPE (tree)))
3321 ast *tTree = tree->left;
3322 tree->left = tree->right;
3323 tree->right = tTree;
3326 /* if right is a literal and */
3327 /* we can find a 2nd literal in a mul-tree then */
3328 /* rearrange the tree */
3329 if (IS_LITERAL (RTYPE (tree)))
3332 ast *litTree = searchLitOp (tree, &parent, "*");
3336 ast *tTree = litTree->left;
3337 litTree->left = tree->right;
3338 tree->right = tTree;
3339 /* both operands in litTree are literal now */
3340 decorateType (parent, resultType);
3344 LRVAL (tree) = RRVAL (tree) = 1;
3345 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3346 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3347 TETYPE (tree) = getSpec (TTYPE (tree) =
3348 computeType (LTYPE (tree),
3355 /*------------------------------------------------------------------*/
3356 /*----------------------------*/
3357 /* unary '+' operator */
3358 /*----------------------------*/
3363 if (!IS_ARITHMETIC (LTYPE (tree)))
3365 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3366 goto errorTreeReturn;
3369 /* if left is a literal then do it */
3370 if (IS_LITERAL (LTYPE (tree)))
3372 tree->type = EX_VALUE;
3373 tree->opval.val = valFromType (LETYPE (tree));
3375 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3379 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3383 /*------------------------------------------------------------------*/
3384 /*----------------------------*/
3386 /*----------------------------*/
3388 /* this is not a unary operation */
3389 /* if both pointers then problem */
3390 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3391 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3393 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3394 goto errorTreeReturn;
3397 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3398 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3400 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3401 goto errorTreeReturn;
3404 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3405 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3407 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3408 goto errorTreeReturn;
3410 /* if they are both literal then */
3411 /* rewrite the tree */
3412 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3414 tree->type = EX_VALUE;
3415 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3416 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3417 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3418 valFromType (RETYPE (tree)));
3419 tree->right = tree->left = NULL;
3420 TETYPE (tree) = getSpec (TTYPE (tree) =
3421 tree->opval.val->type);
3425 /* if the right is a pointer or left is a literal
3426 xchange left & right */
3427 if (IS_ARRAY (RTYPE (tree)) ||
3428 IS_PTR (RTYPE (tree)) ||
3429 IS_LITERAL (LTYPE (tree)))
3431 ast *tTree = tree->left;
3432 tree->left = tree->right;
3433 tree->right = tTree;
3436 /* if right is a literal and */
3437 /* left is also an addition/subtraction with a literal then */
3438 /* rearrange the tree */
3439 if (IS_LITERAL (RTYPE (tree)))
3441 ast *litTree, *parent;
3442 litTree = searchLitOp (tree, &parent, "+-");
3445 if (litTree->opval.op == '+')
3449 ast *tTree = litTree->left;
3450 litTree->left = tree->right;
3451 tree->right = tree->left;
3454 else if (litTree->opval.op == '-')
3456 if (IS_LITERAL (RTYPE (litTree)))
3460 ast *tTree = litTree->left;
3461 litTree->left = tree->right;
3462 tree->right = tTree;
3468 ast *tTree = litTree->right;
3469 litTree->right = tree->right;
3470 tree->right = tTree;
3471 litTree->opval.op = '+';
3472 tree->opval.op = '-';
3475 decorateType (parent, resultType);
3479 LRVAL (tree) = RRVAL (tree) = 1;
3480 /* if the left is a pointer */
3481 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3482 TETYPE (tree) = getSpec (TTYPE (tree) =
3486 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3487 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3488 TETYPE (tree) = getSpec (TTYPE (tree) =
3489 computeType (LTYPE (tree),
3497 /*------------------------------------------------------------------*/
3498 /*----------------------------*/
3500 /*----------------------------*/
3501 case '-': /* can be unary */
3502 /* if right is null then unary */
3506 if (!IS_ARITHMETIC (LTYPE (tree)))
3508 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3509 goto errorTreeReturn;
3512 /* if left is a literal then do it */
3513 if (IS_LITERAL (LTYPE (tree)))
3515 tree->type = EX_VALUE;
3516 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3518 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3521 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3522 TETYPE (tree) = getSpec (TTYPE (tree) =
3523 computeType (LTYPE (tree),
3531 /*------------------------------------------------------------------*/
3532 /*----------------------------*/
3534 /*----------------------------*/
3536 if (!(IS_PTR (LTYPE (tree)) ||
3537 IS_ARRAY (LTYPE (tree)) ||
3538 IS_ARITHMETIC (LTYPE (tree))))
3540 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3541 goto errorTreeReturn;
3544 if (!(IS_PTR (RTYPE (tree)) ||
3545 IS_ARRAY (RTYPE (tree)) ||
3546 IS_ARITHMETIC (RTYPE (tree))))
3548 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3549 goto errorTreeReturn;
3552 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3553 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3554 IS_INTEGRAL (RTYPE (tree))))
3556 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3557 goto errorTreeReturn;
3560 /* if they are both literal then */
3561 /* rewrite the tree */
3562 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3564 tree->type = EX_VALUE;
3565 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3566 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3567 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3568 valFromType (RETYPE (tree)));
3569 tree->right = tree->left = NULL;
3570 TETYPE (tree) = getSpec (TTYPE (tree) =
3571 tree->opval.val->type);
3575 /* if the left & right are equal then zero */
3576 if (isAstEqual (tree->left, tree->right))
3578 tree->type = EX_VALUE;
3579 tree->left = tree->right = NULL;
3580 tree->opval.val = constCharVal (0);
3581 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3585 /* if both of them are pointers or arrays then */
3586 /* the result is going to be an integer */
3587 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3588 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3589 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3591 /* if only the left is a pointer */
3592 /* then result is a pointer */
3593 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3594 TETYPE (tree) = getSpec (TTYPE (tree) =
3598 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3599 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3601 TETYPE (tree) = getSpec (TTYPE (tree) =
3602 computeType (LTYPE (tree),
3608 LRVAL (tree) = RRVAL (tree) = 1;
3610 /* if right is a literal and */
3611 /* left is also an addition/subtraction with a literal then */
3612 /* rearrange the tree */
3613 if (IS_LITERAL (RTYPE (tree))
3614 /* avoid infinite loop */
3615 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3617 ast *litTree, *litParent;
3618 litTree = searchLitOp (tree, &litParent, "+-");
3621 if (litTree->opval.op == '+')
3625 ast *tTree = litTree->left;
3626 litTree->left = litTree->right;
3627 litTree->right = tree->right;
3628 tree->right = tTree;
3629 tree->opval.op = '+';
3630 litTree->opval.op = '-';
3632 else if (litTree->opval.op == '-')
3634 if (IS_LITERAL (RTYPE (litTree)))
3638 ast *tTree = litTree->left;
3639 litTree->left = tree->right;
3640 tree->right = litParent->left;
3641 litParent->left = tTree;
3642 litTree->opval.op = '+';
3644 tree->decorated = 0;
3645 decorateType (tree, resultType);
3651 ast *tTree = litTree->right;
3652 litTree->right = tree->right;
3653 tree->right = tTree;
3656 decorateType (litParent, resultType);
3661 /*------------------------------------------------------------------*/
3662 /*----------------------------*/
3664 /*----------------------------*/
3666 /* can be only integral type */
3667 if (!IS_INTEGRAL (LTYPE (tree)))
3669 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3670 goto errorTreeReturn;
3673 /* if left is a literal then do it */
3674 if (IS_LITERAL (LTYPE (tree)))
3676 tree->type = EX_VALUE;
3677 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3679 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3680 return addCast (tree, resultTypeProp, TRUE);
3683 if (resultType == RESULT_TYPE_BIT &&
3684 IS_UNSIGNED (tree->left->etype) &&
3685 getSize (tree->left->etype) < INTSIZE)
3687 /* promotion rules are responsible for this strange result:
3688 bit -> int -> ~int -> bit
3689 uchar -> int -> ~int -> bit
3691 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3693 /* optimize bit-result, even if we optimize a buggy source */
3694 tree->type = EX_VALUE;
3695 tree->opval.val = constCharVal (1);
3698 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3700 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3703 /*------------------------------------------------------------------*/
3704 /*----------------------------*/
3706 /*----------------------------*/
3708 /* can be pointer */
3709 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3710 !IS_PTR (LTYPE (tree)) &&
3711 !IS_ARRAY (LTYPE (tree)))
3713 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3714 goto errorTreeReturn;
3717 /* if left is another '!' */
3718 if (IS_AST_NOT_OPER (tree->left))
3720 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3722 /* replace double '!!X' by 'X' */
3723 return tree->left->left;
3725 /* remove double '!!X' by 'X ? 1 : 0' */
3726 tree->opval.op = '?';
3727 tree->left = tree->left->left;
3728 tree->right = newNode (':',
3729 newAst_VALUE (constCharVal (1)),
3730 newAst_VALUE (constCharVal (0)));
3731 tree->right->filename = tree->filename;
3732 tree->right->lineno = tree->lineno;
3733 tree->decorated = 0;
3734 return decorateType (tree, resultType);
3737 /* if left is a literal then do it */
3738 if (IS_LITERAL (LTYPE (tree)))
3740 tree->type = EX_VALUE;
3741 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3743 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3747 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3750 /*------------------------------------------------------------------*/
3751 /*----------------------------*/
3753 /*----------------------------*/
3757 TTYPE (tree) = LTYPE (tree);
3758 TETYPE (tree) = LETYPE (tree);
3763 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3767 TTYPE (tree) = TETYPE (tree) = newCharLink();
3771 TTYPE (tree) = TETYPE (tree) = newIntLink();
3776 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3778 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3779 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3780 printTypeChain (LTYPE (tree), stderr);
3781 fprintf (stderr, ",");
3782 printTypeChain (RTYPE (tree), stderr);
3783 fprintf (stderr, "\n");
3784 goto errorTreeReturn;
3787 /* make smaller type only if it's a LEFT_OP */
3788 if (tree->opval.op == LEFT_OP)
3789 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3791 /* if they are both literal then */
3792 /* rewrite the tree */
3793 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3795 tree->type = EX_VALUE;
3796 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3797 valFromType (RETYPE (tree)),
3798 (tree->opval.op == LEFT_OP ? 1 : 0));
3799 tree->right = tree->left = NULL;
3800 TETYPE (tree) = getSpec (TTYPE (tree) =
3801 tree->opval.val->type);
3805 /* see if this is a GETBYTE operation if yes
3808 ast *otree = optimizeGetByte (tree, resultType);
3811 return decorateType (otree, RESULT_TYPE_NONE);
3814 /* see if this is a GETWORD operation if yes
3817 ast *otree = optimizeGetWord (tree, resultType);
3820 return decorateType (otree, RESULT_TYPE_NONE);
3823 LRVAL (tree) = RRVAL (tree) = 1;
3824 if (tree->opval.op == LEFT_OP)
3826 TETYPE (tree) = getSpec (TTYPE (tree) =
3827 computeType (LTYPE (tree),
3834 /* no promotion necessary */
3835 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3836 if (IS_LITERAL (TTYPE (tree)))
3837 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3840 /* if only the right side is a literal & we are
3841 shifting more than size of the left operand then zero */
3842 if (IS_LITERAL (RTYPE (tree)) &&
3843 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3844 (getSize (TETYPE (tree)) * 8))
3846 if (tree->opval.op==LEFT_OP ||
3847 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3849 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3850 (tree->opval.op == LEFT_OP ? "left" : "right"));
3851 tree->type = EX_VALUE;
3852 tree->left = tree->right = NULL;
3853 tree->opval.val = constCharVal (0);
3854 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3861 /*------------------------------------------------------------------*/
3862 /*----------------------------*/
3864 /*----------------------------*/
3865 case CAST: /* change the type */
3866 /* cannot cast to an aggregate type */
3867 if (IS_AGGREGATE (LTYPE (tree)))
3869 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3870 goto errorTreeReturn;
3873 /* make sure the type is complete and sane */
3874 changePointer(LTYPE(tree));
3875 checkTypeSanity(LETYPE(tree), "(cast)");
3878 /* if 'from' and 'to' are the same remove the superfluous cast,
3879 * this helps other optimizations */
3880 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3882 /* mark that the explicit cast has been removed,
3883 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3884 tree->right->values.removedCast = 1;
3888 /* If code memory is read only, then pointers to code memory */
3889 /* implicitly point to constants -- make this explicit */
3891 sym_link *t = LTYPE(tree);
3892 while (t && t->next)
3894 if (IS_CODEPTR(t) && port->mem.code_ro)
3896 if (IS_SPEC(t->next))
3897 SPEC_CONST (t->next) = 1;
3899 DCL_PTR_CONST (t->next) = 1;
3906 /* if the right is a literal replace the tree */
3907 if (IS_LITERAL (RETYPE (tree))) {
3908 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;
3917 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3918 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3919 sym_link *rest = LTYPE(tree)->next;
3920 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3921 TTYPE(tree) = newLink(DECLARATOR);
3922 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3923 TTYPE(tree)->next = rest;
3924 tree->left->opval.lnk = TTYPE(tree);
3927 TTYPE (tree) = LTYPE (tree);
3931 TTYPE (tree) = LTYPE (tree);
3935 #if 0 // this is already checked, now this could be explicit
3936 /* if pointer to struct then check names */
3937 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3938 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3939 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3941 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3942 SPEC_STRUCT(LETYPE(tree))->tag);
3945 if (IS_ADDRESS_OF_OP(tree->right)
3946 && IS_AST_SYM_VALUE (tree->right->left)
3947 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3949 symbol * sym = AST_SYMBOL (tree->right->left);
3950 unsigned int gptype = 0;
3951 unsigned int addr = SPEC_ADDR (sym->etype);
3953 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3954 || TARGET_IS_PIC16) )
3956 switch (SPEC_SCLS (sym->etype))
3959 gptype = GPTYPE_CODE;
3962 gptype = GPTYPE_FAR;
3966 gptype = GPTYPE_NEAR;
3969 gptype = GPTYPE_XSTACK;
3974 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3975 gptype = GPTYPE_NEAR;
3977 addr |= gptype << (8*(GPTRSIZE - 1));
3980 tree->type = EX_VALUE;
3982 valCastLiteral (LTYPE (tree), addr);
3983 TTYPE (tree) = tree->opval.val->type;
3984 TETYPE (tree) = getSpec (TTYPE (tree));
3987 tree->values.literalFromCast = 1;
3991 /* handle offsetof macro: */
3992 /* #define offsetof(TYPE, MEMBER) \ */
3993 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3994 if (IS_ADDRESS_OF_OP(tree->right)
3995 && IS_AST_OP (tree->right->left)
3996 && tree->right->left->opval.op == PTR_OP
3997 && IS_AST_OP (tree->right->left->left)
3998 && tree->right->left->left->opval.op == CAST
3999 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
4001 symbol *element = getStructElement (
4002 SPEC_STRUCT (LETYPE(tree->right->left)),
4003 AST_SYMBOL(tree->right->left->right)
4007 tree->type = EX_VALUE;
4008 tree->opval.val = valCastLiteral (
4011 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
4014 TTYPE (tree) = tree->opval.val->type;
4015 TETYPE (tree) = getSpec (TTYPE (tree));
4022 /* if the right is a literal replace the tree */
4023 if (IS_LITERAL (RETYPE (tree))) {
4025 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
4026 /* rewrite (type *)litaddr
4028 and define type at litaddr temp
4029 (but only if type's storage class is not generic)
4031 ast *newTree = newNode ('&', NULL, NULL);
4034 TTYPE (newTree) = LTYPE (tree);
4035 TETYPE (newTree) = getSpec(LTYPE (tree));
4037 /* define a global symbol at the casted address*/
4038 sym = newSymbol(genSymName (0), 0);
4039 sym->type = LTYPE (tree)->next;
4041 sym->type = newLink (V_VOID);
4042 sym->etype = getSpec(sym->type);
4043 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4044 sym->lineDef = tree->lineno;
4047 SPEC_STAT (sym->etype) = 1;
4048 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4049 SPEC_ABSA(sym->etype) = 1;
4050 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4053 newTree->left = newAst_VALUE(symbolVal(sym));
4054 newTree->left->filename = tree->filename;
4055 newTree->left->lineno = tree->lineno;
4056 LTYPE (newTree) = sym->type;
4057 LETYPE (newTree) = sym->etype;
4058 LLVAL (newTree) = 1;
4059 LRVAL (newTree) = 0;
4060 TLVAL (newTree) = 1;
4064 if (!IS_PTR (LTYPE (tree))) {
4065 tree->type = EX_VALUE;
4067 valCastLiteral (LTYPE (tree),
4068 floatFromVal (valFromType (RTYPE (tree))));
4069 TTYPE (tree) = tree->opval.val->type;
4072 tree->values.literalFromCast = 1;
4073 TETYPE (tree) = getSpec (TTYPE (tree));
4077 TTYPE (tree) = LTYPE (tree);
4081 TETYPE (tree) = getSpec (TTYPE (tree));
4085 /*------------------------------------------------------------------*/
4086 /*----------------------------*/
4087 /* logical &&, || */
4088 /*----------------------------*/
4091 /* each must be arithmetic type or be a pointer */
4092 if (!IS_PTR (LTYPE (tree)) &&
4093 !IS_ARRAY (LTYPE (tree)) &&
4094 !IS_INTEGRAL (LTYPE (tree)))
4096 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4097 goto errorTreeReturn;
4100 if (!IS_PTR (RTYPE (tree)) &&
4101 !IS_ARRAY (RTYPE (tree)) &&
4102 !IS_INTEGRAL (RTYPE (tree)))
4104 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4105 goto errorTreeReturn;
4107 /* if they are both literal then */
4108 /* rewrite the tree */
4109 if (IS_LITERAL (RTYPE (tree)) &&
4110 IS_LITERAL (LTYPE (tree)))
4112 tree->type = EX_VALUE;
4113 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4114 valFromType (RTYPE (tree)),
4116 tree->right = tree->left = NULL;
4117 TETYPE (tree) = getSpec (TTYPE (tree) =
4118 tree->opval.val->type);
4121 LRVAL (tree) = RRVAL (tree) = 1;
4122 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4125 /*------------------------------------------------------------------*/
4126 /*----------------------------*/
4127 /* comparison operators */
4128 /*----------------------------*/
4136 ast *lt = optimizeCompare (tree);
4142 /* if they are pointers they must be castable */
4143 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4145 if (tree->opval.op==EQ_OP &&
4146 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4147 // we cannot cast a gptr to a !gptr: switch the leaves
4148 struct ast *s=tree->left;
4149 tree->left=tree->right;
4152 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4154 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4155 fprintf (stderr, "comparing type ");
4156 printTypeChain (LTYPE (tree), stderr);
4157 fprintf (stderr, "to type ");
4158 printTypeChain (RTYPE (tree), stderr);
4159 fprintf (stderr, "\n");
4160 goto errorTreeReturn;
4163 /* else they should be promotable to one another */
4166 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4167 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4169 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4171 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4172 fprintf (stderr, "comparing type ");
4173 printTypeChain (LTYPE (tree), stderr);
4174 fprintf (stderr, "to type ");
4175 printTypeChain (RTYPE (tree), stderr);
4176 fprintf (stderr, "\n");
4177 goto errorTreeReturn;
4182 CCR_RESULT ccr_result = CCR_OK;
4184 /* if left is integral and right is literal
4185 then check constant range */
4186 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4187 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4188 tree->opval.op, FALSE);
4189 if (ccr_result == CCR_OK &&
4190 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4191 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4192 tree->opval.op, TRUE);
4195 case CCR_ALWAYS_TRUE:
4196 case CCR_ALWAYS_FALSE:
4197 if (!options.lessPedantic)
4198 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4199 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4200 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4207 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4208 if (tree->opval.op == '>' &&
4209 SPEC_USIGN(LETYPE(tree)) &&
4210 IS_LITERAL(RTYPE(tree)) &&
4211 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4213 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4215 /* the parent is an ifx: */
4216 /* if (unsigned value) */
4220 /* (unsigned value) ? 1 : 0 */
4221 tree->opval.op = '?';
4222 tree->right = newNode (':',
4223 newAst_VALUE (constCharVal (1)),
4224 tree->right); /* val 0 */
4225 tree->right->filename = tree->filename;
4226 tree->right->lineno = tree->lineno;
4227 tree->right->left->filename = tree->filename;
4228 tree->right->left->lineno = tree->lineno;
4229 tree->decorated = 0;
4230 return decorateType (tree, resultType);
4233 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4234 if (IS_LITERAL(RTYPE(tree)) &&
4235 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4236 tree->opval.op == EQ_OP &&
4237 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4239 tree->opval.op = '!';
4241 tree->decorated = 0;
4242 return decorateType (tree, resultType);
4245 /* if they are both literal then */
4246 /* rewrite the tree */
4247 if (IS_LITERAL (RTYPE (tree)) &&
4248 IS_LITERAL (LTYPE (tree)))
4250 tree->type = EX_VALUE;
4251 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4252 valFromType (RETYPE (tree)),
4254 tree->right = tree->left = NULL;
4255 TETYPE (tree) = getSpec (TTYPE (tree) =
4256 tree->opval.val->type);
4260 /* if one is 'signed char ' and the other one is 'unsigned char' */
4261 /* it's necessary to promote to int */
4262 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4263 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4265 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4266 if it's possible to use a 'signed char' */
4268 /* is left a 'unsigned char'? */
4269 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4270 /* the value range of a 'unsigned char' is 0...255;
4271 if the actual value is < 128 it can be changed to signed */
4272 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4274 /* now we've got 2 'signed char'! */
4275 SPEC_USIGN (RETYPE (tree)) = 0;
4277 /* same test for the left operand: */
4278 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4279 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4281 SPEC_USIGN (LETYPE (tree)) = 0;
4285 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4286 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4287 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4291 LRVAL (tree) = RRVAL (tree) = 1;
4292 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4294 /* condition transformations */
4296 unsigned transformedOp = 0;
4298 switch (tree->opval.op)
4300 case '<': /* transform (a < b) to !(a >= b) */
4302 transformedOp = GE_OP;
4304 case '>': /* transform (a > b) to !(a <= b) */
4306 transformedOp = LE_OP;
4308 case LE_OP: /* transform (a <= b) to !(a > b) */
4310 transformedOp = '>';
4312 case GE_OP: /* transform (a >= b) to !(a < b) */
4314 transformedOp = '<';
4316 case NE_OP: /* transform (a != b) to !(a == b) */
4318 transformedOp = EQ_OP;
4320 case EQ_OP: /* transform (a == b) to !(a != b) */
4322 transformedOp = NE_OP;
4329 tree->opval.op = transformedOp;
4330 tree->decorated = 0;
4331 tree = newNode ('!', tree, NULL);
4332 tree->filename = tree->left->filename;
4333 tree->lineno = tree->left->lineno;
4334 return decorateType (tree, resultType);
4340 /*------------------------------------------------------------------*/
4341 /*----------------------------*/
4343 /*----------------------------*/
4344 case SIZEOF: /* evaluate wihout code generation */
4345 /* change the type to a integer */
4347 int size = getSize (tree->right->ftype);
4349 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4350 if (!size && !IS_VOID(tree->right->ftype))
4351 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4353 tree->type = EX_VALUE;
4354 tree->opval.val = constVal (buffer);
4355 tree->right = tree->left = NULL;
4356 TETYPE (tree) = getSpec (TTYPE (tree) =
4357 tree->opval.val->type);
4361 /*------------------------------------------------------------------*/
4362 /*----------------------------*/
4364 /*----------------------------*/
4366 /* return typeof enum value */
4367 tree->type = EX_VALUE;
4370 if (IS_SPEC(tree->right->ftype)) {
4371 switch (SPEC_NOUN(tree->right->ftype)) {
4373 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4374 else typeofv = TYPEOF_INT;
4377 typeofv = TYPEOF_FLOAT;
4380 typeofv = TYPEOF_FIXED16X16;
4383 typeofv = TYPEOF_CHAR;
4386 typeofv = TYPEOF_VOID;
4389 typeofv = TYPEOF_STRUCT;
4392 typeofv = TYPEOF_BITFIELD;
4395 typeofv = TYPEOF_BIT;
4398 typeofv = TYPEOF_SBIT;
4404 switch (DCL_TYPE(tree->right->ftype)) {
4406 typeofv = TYPEOF_POINTER;
4409 typeofv = TYPEOF_FPOINTER;
4412 typeofv = TYPEOF_CPOINTER;
4415 typeofv = TYPEOF_GPOINTER;
4418 typeofv = TYPEOF_PPOINTER;
4421 typeofv = TYPEOF_IPOINTER;
4424 typeofv = TYPEOF_ARRAY;
4427 typeofv = TYPEOF_FUNCTION;
4433 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4434 tree->opval.val = constVal (buffer);
4435 tree->right = tree->left = NULL;
4436 TETYPE (tree) = getSpec (TTYPE (tree) =
4437 tree->opval.val->type);
4440 /*------------------------------------------------------------------*/
4441 /*----------------------------*/
4442 /* conditional operator '?' */
4443 /*----------------------------*/
4445 /* the type is value of the colon operator (on the right) */
4446 assert (IS_COLON_OP (tree->right));
4448 /* If already known then replace the tree : optimizer will do it
4449 but faster to do it here. If done before decorating tree->right
4450 this can save generating unused const strings. */
4451 if (IS_LITERAL (LTYPE (tree)))
4453 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4454 return decorateType (tree->right->left, resultTypeProp);
4456 return decorateType (tree->right->right, resultTypeProp);
4459 tree->right = decorateType (tree->right, resultTypeProp);
4461 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4462 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4464 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4465 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4467 if ((valTrue != 0) && (valFalse == 0))
4469 /* assign cond to result */
4470 tree->left->decorated = 0;
4471 return decorateType (tree->left, resultTypeProp);
4473 else if ((valTrue == 0) && (valFalse != 0))
4475 /* assign !cond to result */
4476 tree->opval.op = '!';
4477 tree->decorated = 0;
4479 return decorateType (tree, resultTypeProp);
4483 /* they have the same boolean value, make them equal */
4484 tree->right->left = tree->right->right;
4488 /* if they are equal then replace the tree */
4489 if (isAstEqual (tree->right->left, tree->right->right))
4491 return tree->right->left;
4494 TTYPE (tree) = RTYPE (tree);
4495 TETYPE (tree) = getSpec (TTYPE (tree));
4499 /* if they don't match we have a problem */
4500 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4501 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4503 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4504 goto errorTreeReturn;
4507 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4508 resultType, tree->opval.op);
4509 TETYPE (tree) = getSpec (TTYPE (tree));
4513 #if 0 // assignment operators are converted by the parser
4514 /*------------------------------------------------------------------*/
4515 /*----------------------------*/
4516 /* assignment operators */
4517 /*----------------------------*/
4520 /* for these it must be both must be integral */
4521 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4522 !IS_ARITHMETIC (RTYPE (tree)))
4524 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4525 goto errorTreeReturn;
4528 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4530 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4531 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4535 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4536 goto errorTreeReturn;
4547 /* for these it must be both must be integral */
4548 if (!IS_INTEGRAL (LTYPE (tree)) ||
4549 !IS_INTEGRAL (RTYPE (tree)))
4551 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4552 goto errorTreeReturn;
4555 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4557 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4558 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4562 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4563 goto errorTreeReturn;
4569 /*------------------------------------------------------------------*/
4570 /*----------------------------*/
4572 /*----------------------------*/
4574 if (!(IS_PTR (LTYPE (tree)) ||
4575 IS_ARITHMETIC (LTYPE (tree))))
4577 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4578 goto errorTreeReturn;
4581 if (!(IS_PTR (RTYPE (tree)) ||
4582 IS_ARITHMETIC (RTYPE (tree))))
4584 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4585 goto errorTreeReturn;
4588 TETYPE (tree) = getSpec (TTYPE (tree) =
4589 computeType (LTYPE (tree),
4594 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4595 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4599 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4600 goto errorTreeReturn;
4606 /*------------------------------------------------------------------*/
4607 /*----------------------------*/
4609 /*----------------------------*/
4611 /* this is not a unary operation */
4612 /* if both pointers then problem */
4613 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4615 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4616 goto errorTreeReturn;
4619 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4621 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4622 goto errorTreeReturn;
4625 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4627 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4628 goto errorTreeReturn;
4631 TETYPE (tree) = getSpec (TTYPE (tree) =
4632 computeType (LTYPE (tree),
4637 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4638 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4642 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4643 goto errorTreeReturn;
4646 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4647 tree->opval.op = '=';
4652 /*------------------------------------------------------------------*/
4653 /*----------------------------*/
4654 /* straight assignemnt */
4655 /*----------------------------*/
4657 /* cannot be an aggregate */
4658 if (IS_AGGREGATE (LTYPE (tree)))
4660 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4661 goto errorTreeReturn;
4664 /* they should either match or be castable */
4665 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4667 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4668 printFromToType(RTYPE(tree),LTYPE(tree));
4671 /* if the left side of the tree is of type void
4672 then report error */
4673 if (IS_VOID (LTYPE (tree)))
4675 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4676 printFromToType(RTYPE(tree), LTYPE(tree));
4679 TETYPE (tree) = getSpec (TTYPE (tree) =
4683 if (!tree->initMode ) {
4684 if (IS_CONSTANT(LTYPE(tree)))
4685 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4689 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4690 goto errorTreeReturn;
4695 /*------------------------------------------------------------------*/
4696 /*----------------------------*/
4697 /* comma operator */
4698 /*----------------------------*/
4700 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4703 /*------------------------------------------------------------------*/
4704 /*----------------------------*/
4706 /*----------------------------*/
4709 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4710 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4712 if (tree->left->opval.op == '*' && !tree->left->right)
4713 tree->left = tree->left->left;
4716 /* require a function or pointer to function */
4717 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4719 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4720 goto errorTreeReturn;
4723 /* if there are parms, make sure that
4724 parms are decorate / process / reverse only once */
4726 !tree->right->decorated)
4731 if (IS_FUNCPTR (LTYPE (tree)))
4733 functype = LTYPE (tree)->next;
4734 processFuncPtrArgs (functype);
4737 functype = LTYPE (tree);
4739 if (processParms (tree->left, FUNC_ARGS(functype),
4740 &tree->right, &parmNumber, TRUE))
4742 goto errorTreeReturn;
4745 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4746 !IFFUNC_ISBUILTIN(functype))
4748 reverseParms (tree->right);
4751 TTYPE (tree) = functype->next;
4752 TETYPE (tree) = getSpec (TTYPE (tree));
4756 /*------------------------------------------------------------------*/
4757 /*----------------------------*/
4758 /* return statement */
4759 /*----------------------------*/
4764 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4766 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4767 printFromToType (RTYPE(tree), currFunc->type->next);
4768 goto errorTreeReturn;
4771 if (IS_VOID (currFunc->type->next)
4773 !IS_VOID (RTYPE (tree)))
4775 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4776 goto errorTreeReturn;
4779 /* if there is going to be a casting required then add it */
4780 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4783 decorateType (newNode (CAST,
4784 newAst_LINK (copyLinkChain (currFunc->type->next)),
4794 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4796 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4797 goto errorTreeReturn;
4800 TTYPE (tree) = TETYPE (tree) = NULL;
4803 /*------------------------------------------------------------------*/
4804 /*----------------------------*/
4805 /* switch statement */
4806 /*----------------------------*/
4808 /* the switch value must be an integer */
4809 if (!IS_INTEGRAL (LTYPE (tree)))
4811 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4812 goto errorTreeReturn;
4815 TTYPE (tree) = TETYPE (tree) = NULL;
4818 /*------------------------------------------------------------------*/
4819 /*----------------------------*/
4821 /*----------------------------*/
4823 tree->left = backPatchLabels (tree->left,
4826 TTYPE (tree) = TETYPE (tree) = NULL;
4829 /*------------------------------------------------------------------*/
4830 /*----------------------------*/
4832 /*----------------------------*/
4835 AST_FOR (tree, initExpr) = decorateType (
4836 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4837 AST_FOR (tree, condExpr) = decorateType (
4838 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4839 AST_FOR (tree, loopExpr) = decorateType (
4840 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4842 /* if the for loop is reversible then
4843 reverse it otherwise do what we normally
4849 if (isLoopReversible (tree, &sym, &init, &end))
4850 return reverseLoop (tree, sym, init, end);
4852 return decorateType (createFor (AST_FOR (tree, trueLabel),
4853 AST_FOR (tree, continueLabel),
4854 AST_FOR (tree, falseLabel),
4855 AST_FOR (tree, condLabel),
4856 AST_FOR (tree, initExpr),
4857 AST_FOR (tree, condExpr),
4858 AST_FOR (tree, loopExpr),
4859 tree->left), RESULT_TYPE_NONE);
4862 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4863 "node PARAM shouldn't be processed here");
4864 /* but in processParams() */
4867 TTYPE (tree) = TETYPE (tree) = NULL;
4871 /* some error found this tree will be killed */
4873 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4874 tree->opval.op = NULLOP;
4880 /*-----------------------------------------------------------------*/
4881 /* sizeofOp - processes size of operation */
4882 /*-----------------------------------------------------------------*/
4884 sizeofOp (sym_link * type)
4889 /* make sure the type is complete and sane */
4890 checkTypeSanity(type, "(sizeof)");
4892 /* get the size and convert it to character */
4893 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4894 if (!size && !IS_VOID(type))
4895 werror (E_SIZEOF_INCOMPLETE_TYPE);
4897 /* now convert into value */
4898 return constVal (buff);
4902 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4903 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4904 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4905 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4906 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4907 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4908 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4910 /*-----------------------------------------------------------------*/
4911 /* backPatchLabels - change and or not operators to flow control */
4912 /*-----------------------------------------------------------------*/
4914 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4920 /* while-loops insert a label between the IFX and the condition,
4921 therefore look behind the label too */
4922 if (tree->opval.op == LABEL &&
4924 IS_ANDORNOT (tree->right))
4926 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4930 if (!(IS_ANDORNOT (tree)))
4933 /* if this an and */
4936 static int localLbl = 0;
4939 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4940 localLabel = newSymbol (buffer, NestLevel);
4942 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4944 /* if left is already a IFX then just change the if true label in that */
4945 if (!IS_IFX (tree->left))
4946 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4948 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4949 /* right is a IFX then just join */
4950 if (IS_IFX (tree->right))
4951 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4953 tree->right = createLabel (localLabel, tree->right);
4954 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4956 return newNode (NULLOP, tree->left, tree->right);
4959 /* if this is an or operation */
4962 static int localLbl = 0;
4965 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4966 localLabel = newSymbol (buffer, NestLevel);
4968 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4970 /* if left is already a IFX then just change the if true label in that */
4971 if (!IS_IFX (tree->left))
4972 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4974 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4975 /* right is a IFX then just join */
4976 if (IS_IFX (tree->right))
4977 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4979 tree->right = createLabel (localLabel, tree->right);
4980 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4982 return newNode (NULLOP, tree->left, tree->right);
4988 /* call with exchanged labels */
4989 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4991 /* if left isn't already a IFX */
4992 if (!IS_IFX (tree->left))
4994 tree->left = newNode (IFX, tree->left, NULL);
4995 tree->left->trueLabel = falseLabel;
4996 tree->left->falseLabel = trueLabel;
5003 tree->trueLabel = trueLabel;
5004 tree->falseLabel = falseLabel;
5011 /*-----------------------------------------------------------------*/
5012 /* createBlock - create expression tree for block */
5013 /*-----------------------------------------------------------------*/
5015 createBlock (symbol * decl, ast * body)
5019 /* if the block has nothing */
5023 ex = newNode (BLOCK, NULL, body);
5024 ex->values.sym = decl;
5027 ex->filename = NULL;
5032 /*-----------------------------------------------------------------*/
5033 /* createLabel - creates the expression tree for labels */
5034 /*-----------------------------------------------------------------*/
5036 createLabel (symbol * label, ast * stmnt)
5039 char name[SDCC_NAME_MAX + 1];
5042 /* must create fresh symbol if the symbol name */
5043 /* exists in the symbol table, since there can */
5044 /* be a variable with the same name as the labl */
5045 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5046 (csym->level == label->level))
5047 label = newSymbol (label->name, label->level);
5049 /* change the name before putting it in add _ */
5050 SNPRINTF(name, sizeof(name), "%s", label->name);
5052 /* put the label in the LabelSymbol table */
5053 /* but first check if a label of the same */
5055 if ((csym = findSym (LabelTab, NULL, name)))
5056 werror (E_DUPLICATE_LABEL, label->name);
5058 addSym (LabelTab, label, name, label->level, 0, 0);
5062 label->key = labelKey++;
5063 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5064 rValue->filename = NULL;
5070 /*-----------------------------------------------------------------*/
5071 /* createCase - generates the parsetree for a case statement */
5072 /*-----------------------------------------------------------------*/
5074 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5076 char caseLbl[SDCC_NAME_MAX + 1];
5080 /* if the switch statement does not exist */
5081 /* then case is out of context */
5084 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5088 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5089 /* if not a constant then error */
5090 if (!IS_LITERAL (caseVal->ftype))
5092 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5096 /* if not a integer than error */
5097 if (!IS_INTEGRAL (caseVal->ftype))
5099 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5103 /* find the end of the switch values chain */
5104 if (!(val = swStat->values.switchVals.swVals))
5105 swStat->values.switchVals.swVals = caseVal->opval.val;
5108 /* also order the cases according to value */
5110 int cVal = (int) ulFromVal (caseVal->opval.val);
5111 while (val && (int) ulFromVal (val) < cVal)
5117 /* if we reached the end then */
5120 pval->next = caseVal->opval.val;
5122 else if ((int) ulFromVal (val) == cVal)
5124 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5130 /* we found a value greater than */
5131 /* the current value we must add this */
5132 /* before the value */
5133 caseVal->opval.val->next = val;
5135 /* if this was the first in chain */
5136 if (swStat->values.switchVals.swVals == val)
5137 swStat->values.switchVals.swVals =
5140 pval->next = caseVal->opval.val;
5145 /* create the case label */
5146 SNPRINTF(caseLbl, sizeof(caseLbl),
5148 swStat->values.switchVals.swNum,
5149 (int) ulFromVal (caseVal->opval.val));
5151 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5152 rexpr->filename = 0;
5157 /*-----------------------------------------------------------------*/
5158 /* createDefault - creates the parse tree for the default statement */
5159 /*-----------------------------------------------------------------*/
5161 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5163 char defLbl[SDCC_NAME_MAX + 1];
5165 /* if the switch statement does not exist */
5166 /* then case is out of context */
5169 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5173 if (swStat->values.switchVals.swDefault)
5175 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5180 /* turn on the default flag */
5181 swStat->values.switchVals.swDefault = 1;
5183 /* create the label */
5184 SNPRINTF (defLbl, sizeof(defLbl),
5185 "_default_%d", swStat->values.switchVals.swNum);
5186 return createLabel (newSymbol (defLbl, 0), stmnt);
5189 /*-----------------------------------------------------------------*/
5190 /* createIf - creates the parsetree for the if statement */
5191 /*-----------------------------------------------------------------*/
5193 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5195 static int Lblnum = 0;
5197 symbol *ifTrue, *ifFalse, *ifEnd;
5199 /* if neither exists */
5200 if (!elseBody && !ifBody) {
5201 // if there are no side effects (i++, j() etc)
5202 if (!hasSEFcalls(condAst)) {
5207 /* create the labels */
5208 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5209 ifFalse = newSymbol (buffer, NestLevel);
5210 /* if no else body then end == false */
5215 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5216 ifEnd = newSymbol (buffer, NestLevel);
5219 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5220 ifTrue = newSymbol (buffer, NestLevel);
5224 /* attach the ifTrue label to the top of it body */
5225 ifBody = createLabel (ifTrue, ifBody);
5226 /* attach a goto end to the ifBody if else is present */
5229 ifBody = newNode (NULLOP, ifBody,
5231 newAst_VALUE (symbolVal (ifEnd)),
5233 /* put the elseLabel on the else body */
5234 elseBody = createLabel (ifFalse, elseBody);
5235 /* out the end at the end of the body */
5236 elseBody = newNode (NULLOP,
5238 createLabel (ifEnd, NULL));
5242 ifBody = newNode (NULLOP, ifBody,
5243 createLabel (ifFalse, NULL));
5245 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5246 if (IS_IFX (condAst))
5249 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5251 return newNode (NULLOP, ifTree,
5252 newNode (NULLOP, ifBody, elseBody));
5256 /*-----------------------------------------------------------------*/
5257 /* createDo - creates parse tree for do */
5260 /* _docontinue_n: */
5261 /* condition_expression +-> trueLabel -> _dobody_n */
5263 /* +-> falseLabel-> _dobreak_n */
5265 /*-----------------------------------------------------------------*/
5267 createDo (symbol * trueLabel, symbol * continueLabel,
5268 symbol * falseLabel, ast * condAst, ast * doBody)
5273 /* if the body does not exist then it is simple */
5276 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5277 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5278 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5279 doTree->trueLabel = continueLabel;
5280 doTree->falseLabel = NULL;
5282 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5286 /* otherwise we have a body */
5287 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5289 /* attach the body label to the top */
5290 doBody = createLabel (trueLabel, doBody);
5291 /* attach the continue label to end of body */
5292 doBody = newNode (NULLOP, doBody,
5293 createLabel (continueLabel, NULL));
5295 /* now put the break label at the end */
5296 if (IS_IFX (condAst))
5299 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5301 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5303 /* putting it together */
5304 return newNode (NULLOP, doBody, doTree);
5307 /*-----------------------------------------------------------------*/
5308 /* createFor - creates parse tree for 'for' statement */
5311 /* condExpr +-> trueLabel -> _forbody_n */
5313 /* +-> falseLabel-> _forbreak_n */
5316 /* _forcontinue_n: */
5318 /* goto _forcond_n ; */
5320 /*-----------------------------------------------------------------*/
5322 createFor (symbol * trueLabel, symbol * continueLabel,
5323 symbol * falseLabel, symbol * condLabel,
5324 ast * initExpr, ast * condExpr, ast * loopExpr,
5329 /* if loopexpression not present then we can generate it */
5330 /* the same way as a while */
5332 return newNode (NULLOP, initExpr,
5333 createWhile (trueLabel, continueLabel,
5334 falseLabel, condExpr, forBody));
5335 /* vanilla for statement */
5336 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5338 if (condExpr && !IS_IFX (condExpr))
5339 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5342 /* attach condition label to condition */
5343 condExpr = createLabel (condLabel, condExpr);
5345 /* attach body label to body */
5346 forBody = createLabel (trueLabel, forBody);
5348 /* attach continue to forLoop expression & attach */
5349 /* goto the forcond @ and of loopExpression */
5350 loopExpr = createLabel (continueLabel,
5354 newAst_VALUE (symbolVal (condLabel)),
5356 /* now start putting them together */
5357 forTree = newNode (NULLOP, initExpr, condExpr);
5358 forTree = newNode (NULLOP, forTree, forBody);
5359 forTree = newNode (NULLOP, forTree, loopExpr);
5360 /* finally add the break label */
5361 forTree = newNode (NULLOP, forTree,
5362 createLabel (falseLabel, NULL));
5366 /*-----------------------------------------------------------------*/
5367 /* createWhile - creates parse tree for while statement */
5368 /* the while statement will be created as follows */
5370 /* _while_continue_n: */
5371 /* condition_expression +-> trueLabel -> _while_boby_n */
5373 /* +-> falseLabel -> _while_break_n */
5374 /* _while_body_n: */
5376 /* goto _while_continue_n */
5377 /* _while_break_n: */
5378 /*-----------------------------------------------------------------*/
5380 createWhile (symbol * trueLabel, symbol * continueLabel,
5381 symbol * falseLabel, ast * condExpr, ast * whileBody)
5385 /* put the continue label */
5386 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5387 condExpr = createLabel (continueLabel, condExpr);
5388 condExpr->filename = NULL;
5389 condExpr->lineno = 0;
5391 /* put the body label in front of the body */
5392 whileBody = createLabel (trueLabel, whileBody);
5393 whileBody->filename = NULL;
5394 whileBody->lineno = 0;
5395 /* put a jump to continue at the end of the body */
5396 /* and put break label at the end of the body */
5397 whileBody = newNode (NULLOP,
5400 newAst_VALUE (symbolVal (continueLabel)),
5401 createLabel (falseLabel, NULL)));
5403 /* put it all together */
5404 if (IS_IFX (condExpr))
5405 whileTree = condExpr;
5408 whileTree = newNode (IFX, condExpr, NULL);
5409 /* put the true & false labels in place */
5410 whileTree->trueLabel = trueLabel;
5411 whileTree->falseLabel = falseLabel;
5414 return newNode (NULLOP, whileTree, whileBody);
5417 /*-----------------------------------------------------------------*/
5418 /* isShiftRightLitVal _BitAndLitVal - helper function */
5419 /*-----------------------------------------------------------------*/
5421 isShiftRightLitVal_BitAndLitVal (ast * tree)
5423 /* if this is not a bit and */
5424 if (!IS_BITAND (tree))
5427 /* will look for tree of the form
5428 ( expr >> litval2) & litval1 */
5429 if (!IS_AST_LIT_VALUE (tree->right))
5432 if (!IS_RIGHT_OP (tree->left))
5435 if (!IS_AST_LIT_VALUE (tree->left->right))
5438 return tree->left->left;
5441 /*-----------------------------------------------------------------*/
5442 /* isBitAndPowOf2 - helper function */
5443 /*-----------------------------------------------------------------*/
5445 isBitAndPow2 (ast * tree)
5447 /* if this is not a bit and */
5448 if (!IS_BITAND (tree))
5451 /* will look for tree of the form
5452 ( expr & (1 << litval) */
5453 if (!IS_AST_LIT_VALUE (tree->right))
5456 return powof2 (AST_ULONG_VALUE (tree->right));
5459 /*-----------------------------------------------------------------*/
5460 /* optimizeGetHbit - get highest order bit of the expression */
5461 /*-----------------------------------------------------------------*/
5463 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5468 expr = isShiftRightLitVal_BitAndLitVal(tree);
5471 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5472 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5473 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5476 if (!expr && (resultType == RESULT_TYPE_BIT))
5479 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5485 /* make sure the port supports GETHBIT */
5486 if (port->hasExtBitOp
5487 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5490 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5493 /*-----------------------------------------------------------------*/
5494 /* optimizeGetAbit - get a single bit of the expression */
5495 /*-----------------------------------------------------------------*/
5497 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5502 expr = isShiftRightLitVal_BitAndLitVal(tree);
5505 if (AST_ULONG_VALUE (tree->right) != 1)
5507 count = tree->left->right;
5509 if (!expr && (resultType == RESULT_TYPE_BIT))
5511 int p2 = isBitAndPow2 (tree);
5515 count = newAst_VALUE (valueFromLit (p2));
5521 /* make sure the port supports GETABIT */
5522 if (port->hasExtBitOp
5523 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5526 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5530 /*-----------------------------------------------------------------*/
5531 /* optimizeGetByte - get a byte of the expression */
5532 /*-----------------------------------------------------------------*/
5534 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5540 expr = isShiftRightLitVal_BitAndLitVal(tree);
5543 i = AST_ULONG_VALUE (tree->left->right);
5544 count = tree->left->right;
5545 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5548 if (!expr && resultType == RESULT_TYPE_CHAR)
5550 /* if this is a right shift over a multiple of 8 */
5551 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5553 i = AST_ULONG_VALUE (tree->right);
5554 count = tree->right;
5558 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5561 /* make sure the port supports GETBYTE */
5562 if (port->hasExtBitOp
5563 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5566 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5569 /*-----------------------------------------------------------------*/
5570 /* optimizeGetWord - get two bytes of the expression */
5571 /*-----------------------------------------------------------------*/
5573 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5579 expr = isShiftRightLitVal_BitAndLitVal(tree);
5582 i = AST_ULONG_VALUE (tree->left->right);
5583 count = tree->left->right;
5584 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5587 if (!expr && resultType == RESULT_TYPE_INT)
5589 /* if this is a right shift over a multiple of 8 */
5590 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5592 i = AST_ULONG_VALUE (tree->right);
5593 count = tree->right;
5597 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5600 /* make sure the port supports GETWORD */
5601 if (port->hasExtBitOp
5602 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5605 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5608 /*-----------------------------------------------------------------*/
5609 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5610 /*-----------------------------------------------------------------*/
5612 optimizeRRCRLC (ast * root)
5614 /* will look for trees of the form
5615 (?expr << 1) | (?expr >> 7) or
5616 (?expr >> 7) | (?expr << 1) will make that
5617 into a RLC : operation ..
5619 (?expr >> 1) | (?expr << 7) or
5620 (?expr << 7) | (?expr >> 1) will make that
5621 into a RRC operation
5622 note : by 7 I mean (number of bits required to hold the
5624 /* if the root operation is not a | operation then not */
5625 if (!IS_BITOR (root))
5628 /* I have to think of a better way to match patterns this sucks */
5629 /* that aside let's start looking for the first case : I use a
5630 negative check a lot to improve the efficiency */
5631 /* (?expr << 1) | (?expr >> 7) */
5632 if (IS_LEFT_OP (root->left) &&
5633 IS_RIGHT_OP (root->right))
5636 if (!SPEC_USIGN (TETYPE (root->left->left)))
5639 if (!IS_AST_LIT_VALUE (root->left->right) ||
5640 !IS_AST_LIT_VALUE (root->right->right))
5643 /* make sure it is the same expression */
5644 if (!isAstEqual (root->left->left,
5648 if (AST_ULONG_VALUE (root->left->right) != 1)
5651 if (AST_ULONG_VALUE (root->right->right) !=
5652 (getSize (TTYPE (root->left->left)) * 8 - 1))
5655 /* make sure the port supports RLC */
5656 if (port->hasExtBitOp
5657 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5660 /* whew got the first case : create the AST */
5661 return newNode (RLC, root->left->left, NULL);
5665 /* check for second case */
5666 /* (?expr >> 7) | (?expr << 1) */
5667 if (IS_LEFT_OP (root->right) &&
5668 IS_RIGHT_OP (root->left))
5671 if (!SPEC_USIGN (TETYPE (root->left->left)))
5674 if (!IS_AST_LIT_VALUE (root->left->right) ||
5675 !IS_AST_LIT_VALUE (root->right->right))
5678 /* make sure it is the same symbol */
5679 if (!isAstEqual (root->left->left,
5683 if (AST_ULONG_VALUE (root->right->right) != 1)
5686 if (AST_ULONG_VALUE (root->left->right) !=
5687 (getSize (TTYPE (root->left->left)) * 8 - 1))
5690 /* make sure the port supports RLC */
5691 if (port->hasExtBitOp
5692 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5695 /* whew got the first case : create the AST */
5696 return newNode (RLC, root->left->left, NULL);
5701 /* third case for RRC */
5702 /* (?symbol >> 1) | (?symbol << 7) */
5703 if (IS_LEFT_OP (root->right) &&
5704 IS_RIGHT_OP (root->left))
5707 if (!SPEC_USIGN (TETYPE (root->left->left)))
5710 if (!IS_AST_LIT_VALUE (root->left->right) ||
5711 !IS_AST_LIT_VALUE (root->right->right))
5714 /* make sure it is the same symbol */
5715 if (!isAstEqual (root->left->left,
5719 if (AST_ULONG_VALUE (root->left->right) != 1)
5722 if (AST_ULONG_VALUE (root->right->right) !=
5723 (getSize (TTYPE (root->left->left)) * 8 - 1))
5726 /* make sure the port supports RRC */
5727 if (port->hasExtBitOp
5728 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5731 /* whew got the first case : create the AST */
5732 return newNode (RRC, root->left->left, NULL);
5736 /* fourth and last case for now */
5737 /* (?symbol << 7) | (?symbol >> 1) */
5738 if (IS_RIGHT_OP (root->right) &&
5739 IS_LEFT_OP (root->left))
5742 if (!SPEC_USIGN (TETYPE (root->left->left)))
5745 if (!IS_AST_LIT_VALUE (root->left->right) ||
5746 !IS_AST_LIT_VALUE (root->right->right))
5749 /* make sure it is the same symbol */
5750 if (!isAstEqual (root->left->left,
5754 if (AST_ULONG_VALUE (root->right->right) != 1)
5757 if (AST_ULONG_VALUE (root->left->right) !=
5758 (getSize (TTYPE (root->left->left)) * 8 - 1))
5761 /* make sure the port supports RRC */
5762 if (port->hasExtBitOp
5763 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5766 /* whew got the first case : create the AST */
5767 return newNode (RRC, root->left->left, NULL);
5771 /* not found return root */
5775 /*-----------------------------------------------------------------*/
5776 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5777 /*-----------------------------------------------------------------*/
5779 optimizeSWAP (ast * root)
5781 /* will look for trees of the form
5782 (?expr << 4) | (?expr >> 4) or
5783 (?expr >> 4) | (?expr << 4) will make that
5784 into a SWAP : operation ..
5785 note : by 4 I mean (number of bits required to hold the
5787 /* if the root operation is not a | operation then not */
5788 if (!IS_BITOR (root))
5791 /* (?expr << 4) | (?expr >> 4) */
5792 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5793 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5796 if (!SPEC_USIGN (TETYPE (root->left->left)))
5799 if (!IS_AST_LIT_VALUE (root->left->right) ||
5800 !IS_AST_LIT_VALUE (root->right->right))
5803 /* make sure it is the same expression */
5804 if (!isAstEqual (root->left->left,
5808 if (AST_ULONG_VALUE (root->left->right) !=
5809 (getSize (TTYPE (root->left->left)) * 4))
5812 if (AST_ULONG_VALUE (root->right->right) !=
5813 (getSize (TTYPE (root->left->left)) * 4))
5816 /* make sure the port supports SWAP */
5817 if (port->hasExtBitOp
5818 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5821 /* found it : create the AST */
5822 return newNode (SWAP, root->left->left, NULL);
5826 /* not found return root */
5830 /*-----------------------------------------------------------------*/
5831 /* optimizeCompare - optimizes compares for bit variables */
5832 /*-----------------------------------------------------------------*/
5834 optimizeCompare (ast * root)
5836 ast *optExpr = NULL;
5839 unsigned int litValue;
5841 /* if nothing then return nothing */
5845 /* if not a compare op then do leaves */
5846 if (!IS_COMPARE_OP (root))
5848 root->left = optimizeCompare (root->left);
5849 root->right = optimizeCompare (root->right);
5853 /* if left & right are the same then depending
5854 of the operation do */
5855 if (isAstEqual (root->left, root->right))
5857 switch (root->opval.op)
5862 optExpr = newAst_VALUE (constCharVal (0));
5867 optExpr = newAst_VALUE (constCharVal (1));
5871 return decorateType (optExpr, RESULT_TYPE_NONE);
5874 vleft = (root->left->type == EX_VALUE ?
5875 root->left->opval.val : NULL);
5877 vright = (root->right->type == EX_VALUE ?
5878 root->right->opval.val : NULL);
5880 /* if left is a BITVAR in BITSPACE */
5881 /* and right is a LITERAL then */
5882 /* optimize else do nothing */
5883 if (vleft && vright &&
5884 IS_BITVAR (vleft->etype) &&
5885 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5886 IS_LITERAL (vright->etype))
5889 /* if right side > 1 then comparison may never succeed */
5890 if ((litValue = (int) ulFromVal (vright)) > 1)
5892 werror (W_BAD_COMPARE);
5898 switch (root->opval.op)
5900 case '>': /* bit value greater than 1 cannot be */
5901 werror (W_BAD_COMPARE);
5905 case '<': /* bit value < 1 means 0 */
5907 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5910 case LE_OP: /* bit value <= 1 means no check */
5911 optExpr = newAst_VALUE (vright);
5914 case GE_OP: /* bit value >= 1 means only check for = */
5916 optExpr = newAst_VALUE (vleft);
5921 { /* literal is zero */
5922 switch (root->opval.op)
5924 case '<': /* bit value < 0 cannot be */
5925 werror (W_BAD_COMPARE);
5929 case '>': /* bit value > 0 means 1 */
5931 optExpr = newAst_VALUE (vleft);
5934 case LE_OP: /* bit value <= 0 means no check */
5935 case GE_OP: /* bit value >= 0 means no check */
5936 werror (W_BAD_COMPARE);
5940 case EQ_OP: /* bit == 0 means ! of bit */
5941 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5945 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5946 } /* end-of-if of BITVAR */
5952 /*-----------------------------------------------------------------*/
5953 /* addSymToBlock : adds the symbol to the first block we find */
5954 /*-----------------------------------------------------------------*/
5956 addSymToBlock (symbol * sym, ast * tree)
5958 /* reached end of tree or a leaf */
5959 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5963 if (IS_AST_OP (tree) &&
5964 tree->opval.op == BLOCK)
5967 symbol *lsym = copySymbol (sym);
5969 lsym->next = AST_VALUES (tree, sym);
5970 AST_VALUES (tree, sym) = lsym;
5974 addSymToBlock (sym, tree->left);
5975 addSymToBlock (sym, tree->right);
5978 /*-----------------------------------------------------------------*/
5979 /* processRegParms - do processing for register parameters */
5980 /*-----------------------------------------------------------------*/
5982 processRegParms (value * args, ast * body)
5986 if (IS_REGPARM (args->etype))
5987 addSymToBlock (args->sym, body);
5992 /*-----------------------------------------------------------------*/
5993 /* resetParmKey - resets the operandkeys for the symbols */
5994 /*-----------------------------------------------------------------*/
5995 DEFSETFUNC (resetParmKey)
6006 /*------------------------------------------------------------------*/
6007 /* fixupInlineLabel - change a label in an inlined function so that */
6008 /* it is always unique no matter how many times */
6009 /* the function is inlined. */
6010 /*------------------------------------------------------------------*/
6012 fixupInlineLabel (symbol * sym)
6014 char name[SDCC_NAME_MAX + 1];
6016 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
6017 strcpy (sym->name, name);
6020 /*------------------------------------------------------------------*/
6021 /* copyAstLoc - copy location information (file, line, block, etc.) */
6022 /* from one ast node to another */
6023 /*------------------------------------------------------------------*/
6025 copyAstLoc (ast * dest, ast * src)
6027 dest->filename = src->filename;
6028 dest->lineno = src->lineno;
6029 dest->level = src->level;
6030 dest->block = src->block;
6031 dest->seqPoint = src->seqPoint;
6034 /*-----------------------------------------------------------------*/
6035 /* fixupInline - perform various fixups on an inline function tree */
6036 /* to take into account that it is no longer a */
6037 /* stand-alone function. */
6038 /*-----------------------------------------------------------------*/
6040 fixupInline (ast * tree, int level)
6042 int savedBlockno = currBlockno;
6044 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6048 currBlockno = ++blockNo;
6051 /* Add any declared variables back into the symbol table */
6052 decls = tree->values.sym;
6055 decls->level = level;
6056 decls->block = currBlockno;
6057 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6058 decls = decls->next;
6062 tree->level = level;
6063 tree->block = currBlockno;
6065 /* Update symbols */
6066 if (IS_AST_VALUE (tree) &&
6067 tree->opval.val->sym)
6069 symbol * sym = tree->opval.val->sym;
6072 sym->block = currBlockno;
6075 SYM_SPIL_LOC (sym) = NULL;
6078 /* If the symbol is a label, we need to renumber it */
6080 fixupInlineLabel (sym);
6083 /* Update IFX target labels */
6084 if (tree->type == EX_OP && tree->opval.op == IFX)
6086 if (tree->trueLabel)
6087 fixupInlineLabel (tree->trueLabel);
6088 if (tree->falseLabel)
6089 fixupInlineLabel (tree->falseLabel);
6092 /* Replace RETURN with optional assignment and a GOTO to the end */
6093 /* of the inlined function */
6094 if (tree->type == EX_OP && tree->opval.op == RETURN)
6096 ast * assignTree = NULL;
6099 if (inlineState.retsym && tree->right)
6101 assignTree = newNode ('=',
6102 newAst_VALUE (symbolVal (inlineState.retsym)),
6104 copyAstLoc (assignTree, tree);
6107 gotoTree = newNode (GOTO,
6108 newAst_VALUE (symbolVal (inlineState.retlab)),
6110 copyAstLoc (gotoTree, tree);
6112 tree->opval.op = NULLOP;
6113 tree->left = assignTree;
6114 tree->right = gotoTree;
6117 /* Update any children */
6119 fixupInline (tree->left, level);
6121 fixupInline (tree->right, level);
6123 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6125 symbol * label = tree->left->opval.val->sym;
6127 label->key = labelKey++;
6128 /* Add this label back into the symbol table */
6129 addSym (LabelTab, label, label->name, label->level, 0, 0);
6132 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6135 currBlockno = savedBlockno;
6139 /*-----------------------------------------------------------------*/
6140 /* inlineAddDecl - add a variable declaration to an ast block. It */
6141 /* is also added to the symbol table if addSymTab */
6143 /*-----------------------------------------------------------------*/
6145 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6148 SYM_SPIL_LOC (sym) = NULL;
6152 symbol **decl = &(block->values.sym);
6154 sym->level = block->level;
6155 sym->block = block->block;
6159 if (strcmp ((*decl)->name, sym->name) == 0)
6161 decl = &( (*decl)->next );
6167 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6172 /*-----------------------------------------------------------------*/
6173 /* inlineTempVar - create a temporary variable for inlining */
6174 /*-----------------------------------------------------------------*/
6176 inlineTempVar (sym_link * type, int level)
6180 sym = newSymbol (genSymName(level), level );
6181 sym->type = copyLinkChain (type);
6182 sym->etype = getSpec(sym->type);
6183 SPEC_SCLS (sym->etype) = S_AUTO;
6184 SPEC_OCLS (sym->etype) = NULL;
6185 SPEC_EXTR (sym->etype) = 0;
6186 SPEC_STAT (sym->etype) = 0;
6187 if IS_SPEC (sym->type)
6188 SPEC_VOLATILE (sym->type) = 0;
6190 DCL_PTR_VOLATILE (sym->type) = 0;
6191 SPEC_ABSA (sym->etype) = 0;
6196 /*-----------------------------------------------------------------*/
6197 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6198 /*-----------------------------------------------------------------*/
6200 inlineFindParmRecurse (ast * parms, int *index)
6205 if (parms->type == EX_OP && parms->opval.op == PARAM)
6209 p=inlineFindParmRecurse (parms->left, index);
6212 p=inlineFindParmRecurse (parms->right, index);
6222 /*-----------------------------------------------------------------*/
6223 /* inlineFindParm - search an ast tree of parameters to find one */
6224 /* at a particular index (0=first parameter). */
6225 /* Returns NULL if not found. */
6226 /*-----------------------------------------------------------------*/
6228 inlineFindParm (ast * parms, int index)
6230 return inlineFindParmRecurse (parms, &index);
6233 /*-----------------------------------------------------------------*/
6234 /* expandInlineFuncs - replace calls to inline functions with the */
6235 /* function itself */
6236 /*-----------------------------------------------------------------*/
6238 expandInlineFuncs (ast * tree, ast * block)
6240 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6241 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6243 symbol * func = tree->left->opval.val->sym;
6246 /* The symbol is probably not bound yet, so find the real one */
6247 csym = findSymWithLevel (SymbolTab, func);
6251 /* Is this an inline function that we can inline? */
6252 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6254 symbol * retsym = NULL;
6262 /* Generate a label for the inlined function to branch to */
6263 /* in case it contains a return statement */
6264 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6267 inlineState.retlab = retlab;
6269 /* Build the subtree for the inlined function in the form: */
6270 /* { //inlinetree block */
6271 /* { //inlinetree2 block */
6272 /* inline_function_code; */
6276 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6277 copyAstLoc (temptree, tree);
6278 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6279 copyAstLoc (temptree, tree);
6280 temptree = newNode (BLOCK, NULL, temptree);
6281 copyAstLoc (temptree, tree);
6282 inlinetree2 = temptree;
6283 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6284 copyAstLoc (inlinetree, tree);
6286 /* To pass parameters to the inlined function, we need some */
6287 /* intermediate variables. This avoids scoping problems */
6288 /* when the parameter declaration names are used differently */
6289 /* during the function call. For example, a function */
6290 /* declared as func(int x, int y) but called as func(y,x). */
6291 /* { //inlinetree block */
6292 /* type1 temparg1 = argument1; */
6294 /* typen tempargn = argumentn; */
6295 /* { //inlinetree2 block */
6296 /* type1 param1 = temparg1; */
6298 /* typen paramn = tempargn; */
6299 /* inline_function_code; */
6303 args = FUNC_ARGS (func->type);
6310 ast * passedarg = inlineFindParm (tree->right, argIndex);
6314 werror(E_TOO_FEW_PARMS);
6318 temparg = inlineTempVar (args->sym->type, tree->level+1);
6319 inlineAddDecl (temparg, inlinetree, FALSE);
6321 assigntree = newNode ('=',
6322 newAst_VALUE (symbolVal (temparg)),
6324 assigntree->initMode=1; // tell that assignment is initializer
6325 inlinetree->right = newNode (NULLOP,
6329 parm = copySymbol (args->sym);
6330 inlineAddDecl (parm, inlinetree2, FALSE);
6333 assigntree = newNode ('=',
6334 newAst_VALUE (symbolVal (parm)),
6335 newAst_VALUE (symbolVal (temparg)));
6336 assigntree->initMode=1; // tell that assignment is initializer
6337 inlinetree2->right = newNode (NULLOP,
6339 inlinetree2->right);
6345 /* Handle the return type */
6346 if (!IS_VOID (func->type->next))
6348 /* Create a temporary symbol to hold the return value and */
6349 /* join it with the inlined function using the comma */
6350 /* operator. The fixupInline function will take care of */
6351 /* changing return statements into assignments to retsym. */
6352 /* (parameter passing and return label omitted for clarity) */
6353 /* rettype retsym; */
6355 /* {{inline_function_code}}, retsym */
6357 retsym = inlineTempVar (func->type->next, tree->level);
6358 inlineAddDecl (retsym, block, TRUE);
6360 tree->opval.op = ',';
6361 tree->left = inlinetree;
6362 tree->right = newAst_VALUE (symbolVal (retsym));
6366 tree->opval.op = NULLOP;
6368 tree->right = inlinetree;
6370 inlineState.retsym = retsym;
6372 /* Renumber the various internal counters on the inlined */
6373 /* function's tree nodes and symbols. Add the inlined */
6374 /* function's local variables to the appropriate scope(s). */
6375 /* Convert inlined return statements to an assignment to */
6376 /* retsym (if needed) and a goto retlab. */
6377 fixupInline (inlinetree, inlinetree->level);
6378 inlineState.count++;
6382 /* Recursively continue to search for functions to inline. */
6383 if (IS_AST_OP (tree))
6385 if (tree->opval.op == BLOCK)
6389 expandInlineFuncs (tree->left, block);
6391 expandInlineFuncs (tree->right, block);
6395 /*-----------------------------------------------------------------*/
6396 /* createFunction - This is the key node that calls the iCode for */
6397 /* generating the code for a function. Note code */
6398 /* is generated function by function, later when */
6399 /* add inter-procedural analysis this will change */
6400 /*-----------------------------------------------------------------*/
6402 createFunction (symbol * name, ast * body)
6408 iCode *piCode = NULL;
6410 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6411 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6413 /* if check function return 0 then some problem */
6414 if (checkFunction (name, NULL) == 0)
6417 /* create a dummy block if none exists */
6419 body = newNode (BLOCK, NULL, NULL);
6423 /* check if the function name already in the symbol table */
6424 if ((csym = findSym (SymbolTab, NULL, name->name)))
6427 /* special case for compiler defined functions
6428 we need to add the name to the publics list : this
6429 actually means we are now compiling the compiler
6433 addSet (&publics, name);
6438 addSymChain (&name);
6439 allocVariables (name);
6441 name->lastLine = lexLineno;
6444 /* set the stack pointer */
6445 stackPtr = -port->stack.direction * port->stack.call_overhead;
6448 if (IFFUNC_ISISR (name->type))
6449 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6451 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6453 if (options.useXstack)
6454 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6456 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6459 fetype = getSpec (name->type); /* get the specifier for the function */
6460 /* if this is a reentrant function then */
6461 if (IFFUNC_ISREENT (name->type))
6464 inlineState.count = 0;
6465 expandInlineFuncs (body, NULL);
6467 if (FUNC_ISINLINE (name->type))
6468 name->funcTree = copyAst (body);
6470 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6472 /* do processing for parameters that are passed in registers */
6473 processRegParms (FUNC_ARGS(name->type), body);
6475 /* set the stack pointer */
6479 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6481 /* allocate & autoinit the block variables */
6482 processBlockVars (body, &stack, ALLOCATE);
6484 /* name needs to be mangled */
6485 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6487 body = resolveSymbols (body); /* resolve the symbols */
6488 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6490 /* save the stack information */
6491 if (options.useXstack)
6492 name->xstack = SPEC_STAK (fetype) = stack;
6494 name->stack = SPEC_STAK (fetype) = stack;
6496 ex = newAst_VALUE (symbolVal (name)); /* create name */
6497 ex = newNode (FUNCTION, ex, body);
6498 ex->values.args = FUNC_ARGS(name->type);
6500 if (options.dump_tree)
6505 /* Do not generate code for inline functions unless extern also. */
6507 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6510 /* Temporary hack: always generate code for static inline functions. */
6511 /* Ideally static inline functions should only be generated if needed. */
6512 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6516 /* create the node & generate intermediate code */
6518 codeOutBuf = &code->oBuf;
6519 piCode = iCodeFromAst (ex);
6520 name->generated = 1;
6525 eBBlockFromiCode (piCode);
6527 /* if there are any statics then do them */
6530 GcurMemmap = statsg;
6531 codeOutBuf = &statsg->oBuf;
6532 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6538 /* dealloc the block variables */
6539 processBlockVars (body, &stack, DEALLOCATE);
6540 outputDebugStackSymbols();
6541 /* deallocate paramaters */
6542 deallocParms (FUNC_ARGS(name->type));
6544 if (IFFUNC_ISREENT (name->type))
6547 /* we are done freeup memory & cleanup */
6549 if (port->reset_labelKey)
6552 FUNC_HASBODY(name->type) = 1;
6553 addSet (&operKeyReset, name);
6554 applyToSet (operKeyReset, resetParmKey);
6559 cleanUpLevel (LabelTab, 0);
6560 cleanUpBlock (StructTab, 1);
6561 cleanUpBlock (TypedefTab, 1);
6563 xstack->syms = NULL;
6564 istack->syms = NULL;
6569 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6570 /*-----------------------------------------------------------------*/
6571 /* ast_print : prints the ast (for debugging purposes) */
6572 /*-----------------------------------------------------------------*/
6574 void ast_print (ast * tree, FILE *outfile, int indent)
6579 /* can print only decorated trees */
6580 if (!tree->decorated) return;
6582 /* if any child is an error | this one is an error do nothing */
6583 if (tree->isError ||
6584 (tree->left && tree->left->isError) ||
6585 (tree->right && tree->right->isError)) {
6586 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6590 /* print the line */
6591 /* if not block & function */
6592 if (tree->type == EX_OP &&
6593 (tree->opval.op != FUNCTION &&
6594 tree->opval.op != BLOCK &&
6595 tree->opval.op != NULLOP)) {
6598 if (tree->opval.op == FUNCTION) {
6600 value *args=FUNC_ARGS(tree->left->opval.val->type);
6601 fprintf(outfile,"FUNCTION (%s=%p) type (",
6602 tree->left->opval.val->name, tree);
6603 printTypeChain (tree->left->opval.val->type->next,outfile);
6604 fprintf(outfile,") args (");
6607 fprintf (outfile, ", ");
6609 printTypeChain (args ? args->type : NULL, outfile);
6611 args= args ? args->next : NULL;
6613 fprintf(outfile,")\n");
6614 ast_print(tree->left,outfile,indent);
6615 ast_print(tree->right,outfile,indent);
6618 if (tree->opval.op == BLOCK) {
6619 symbol *decls = tree->values.sym;
6620 INDENT(indent,outfile);
6621 fprintf(outfile,"{\n");
6623 INDENT(indent+2,outfile);
6624 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6625 decls->name, decls);
6626 printTypeChain(decls->type,outfile);
6627 fprintf(outfile,")\n");
6629 decls = decls->next;
6631 ast_print(tree->right,outfile,indent+2);
6632 INDENT(indent,outfile);
6633 fprintf(outfile,"}\n");
6636 if (tree->opval.op == NULLOP) {
6637 ast_print(tree->left,outfile,indent);
6638 ast_print(tree->right,outfile,indent);
6641 INDENT(indent,outfile);
6643 /*------------------------------------------------------------------*/
6644 /*----------------------------*/
6645 /* leaf has been reached */
6646 /*----------------------------*/
6647 /* if this is of type value */
6648 /* just get the type */
6649 if (tree->type == EX_VALUE) {
6651 if (IS_LITERAL (tree->opval.val->etype)) {
6652 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6653 if (SPEC_USIGN (tree->opval.val->etype))
6654 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6656 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6657 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6658 floatFromVal(tree->opval.val));
6659 } else if (tree->opval.val->sym) {
6660 /* if the undefined flag is set then give error message */
6661 if (tree->opval.val->sym->undefined) {
6662 fprintf(outfile,"UNDEFINED SYMBOL ");
6664 fprintf(outfile,"SYMBOL ");
6666 fprintf(outfile,"(%s=%p @ %p)",
6667 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6670 fprintf(outfile," type (");
6671 printTypeChain(tree->ftype,outfile);
6672 fprintf(outfile,")\n");
6674 fprintf(outfile,"\n");
6679 /* if type link for the case of cast */
6680 if (tree->type == EX_LINK) {
6681 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6682 printTypeChain(tree->opval.lnk,outfile);
6683 fprintf(outfile,")\n");
6688 /* depending on type of operator do */
6690 switch (tree->opval.op) {
6691 /*------------------------------------------------------------------*/
6692 /*----------------------------*/
6694 /*----------------------------*/
6696 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6697 printTypeChain(tree->ftype,outfile);
6698 fprintf(outfile,")\n");
6699 ast_print(tree->left,outfile,indent+2);
6700 ast_print(tree->right,outfile,indent+2);
6703 /*------------------------------------------------------------------*/
6704 /*----------------------------*/
6706 /*----------------------------*/
6708 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6709 printTypeChain(tree->ftype,outfile);
6710 fprintf(outfile,")\n");
6711 ast_print(tree->left,outfile,indent+2);
6712 ast_print(tree->right,outfile,indent+2);
6715 /*------------------------------------------------------------------*/
6716 /*----------------------------*/
6717 /* struct/union pointer */
6718 /*----------------------------*/
6720 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6721 printTypeChain(tree->ftype,outfile);
6722 fprintf(outfile,")\n");
6723 ast_print(tree->left,outfile,indent+2);
6724 ast_print(tree->right,outfile,indent+2);
6727 /*------------------------------------------------------------------*/
6728 /*----------------------------*/
6729 /* ++/-- operation */
6730 /*----------------------------*/
6733 fprintf(outfile,"post-");
6735 fprintf(outfile,"pre-");
6736 fprintf(outfile,"INC_OP (%p) type (",tree);
6737 printTypeChain(tree->ftype,outfile);
6738 fprintf(outfile,")\n");
6739 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6740 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6745 fprintf(outfile,"post-");
6747 fprintf(outfile,"pre-");
6748 fprintf(outfile,"DEC_OP (%p) type (",tree);
6749 printTypeChain(tree->ftype,outfile);
6750 fprintf(outfile,")\n");
6751 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6752 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6755 /*------------------------------------------------------------------*/
6756 /*----------------------------*/
6758 /*----------------------------*/
6761 fprintf(outfile,"& (%p) type (",tree);
6762 printTypeChain(tree->ftype,outfile);
6763 fprintf(outfile,")\n");
6764 ast_print(tree->left,outfile,indent+2);
6765 ast_print(tree->right,outfile,indent+2);
6767 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6768 printTypeChain(tree->ftype,outfile);
6769 fprintf(outfile,")\n");
6770 ast_print(tree->left,outfile,indent+2);
6771 ast_print(tree->right,outfile,indent+2);
6774 /*----------------------------*/
6776 /*----------------------------*/
6778 fprintf(outfile,"OR (%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);
6784 /*------------------------------------------------------------------*/
6785 /*----------------------------*/
6787 /*----------------------------*/
6789 fprintf(outfile,"XOR (%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);
6796 /*------------------------------------------------------------------*/
6797 /*----------------------------*/
6799 /*----------------------------*/
6801 fprintf(outfile,"DIV (%p) type (",tree);
6802 printTypeChain(tree->ftype,outfile);
6803 fprintf(outfile,")\n");
6804 ast_print(tree->left,outfile,indent+2);
6805 ast_print(tree->right,outfile,indent+2);
6807 /*------------------------------------------------------------------*/
6808 /*----------------------------*/
6810 /*----------------------------*/
6812 fprintf(outfile,"MOD (%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);
6819 /*------------------------------------------------------------------*/
6820 /*----------------------------*/
6821 /* address dereference */
6822 /*----------------------------*/
6823 case '*': /* can be unary : if right is null then unary operation */
6825 fprintf(outfile,"DEREF (%p) type (",tree);
6826 printTypeChain(tree->ftype,outfile);
6827 fprintf(outfile,")\n");
6828 ast_print(tree->left,outfile,indent+2);
6831 /*------------------------------------------------------------------*/
6832 /*----------------------------*/
6833 /* multiplication */
6834 /*----------------------------*/
6835 fprintf(outfile,"MULT (%p) type (",tree);
6836 printTypeChain(tree->ftype,outfile);
6837 fprintf(outfile,")\n");
6838 ast_print(tree->left,outfile,indent+2);
6839 ast_print(tree->right,outfile,indent+2);
6843 /*------------------------------------------------------------------*/
6844 /*----------------------------*/
6845 /* unary '+' operator */
6846 /*----------------------------*/
6850 fprintf(outfile,"UPLUS (%p) type (",tree);
6851 printTypeChain(tree->ftype,outfile);
6852 fprintf(outfile,")\n");
6853 ast_print(tree->left,outfile,indent+2);
6855 /*------------------------------------------------------------------*/
6856 /*----------------------------*/
6858 /*----------------------------*/
6859 fprintf(outfile,"ADD (%p) type (",tree);
6860 printTypeChain(tree->ftype,outfile);
6861 fprintf(outfile,")\n");
6862 ast_print(tree->left,outfile,indent+2);
6863 ast_print(tree->right,outfile,indent+2);
6866 /*------------------------------------------------------------------*/
6867 /*----------------------------*/
6869 /*----------------------------*/
6870 case '-': /* can be unary */
6872 fprintf(outfile,"UMINUS (%p) type (",tree);
6873 printTypeChain(tree->ftype,outfile);
6874 fprintf(outfile,")\n");
6875 ast_print(tree->left,outfile,indent+2);
6877 /*------------------------------------------------------------------*/
6878 /*----------------------------*/
6880 /*----------------------------*/
6881 fprintf(outfile,"SUB (%p) type (",tree);
6882 printTypeChain(tree->ftype,outfile);
6883 fprintf(outfile,")\n");
6884 ast_print(tree->left,outfile,indent+2);
6885 ast_print(tree->right,outfile,indent+2);
6888 /*------------------------------------------------------------------*/
6889 /*----------------------------*/
6891 /*----------------------------*/
6893 fprintf(outfile,"COMPL (%p) type (",tree);
6894 printTypeChain(tree->ftype,outfile);
6895 fprintf(outfile,")\n");
6896 ast_print(tree->left,outfile,indent+2);
6898 /*------------------------------------------------------------------*/
6899 /*----------------------------*/
6901 /*----------------------------*/
6903 fprintf(outfile,"NOT (%p) type (",tree);
6904 printTypeChain(tree->ftype,outfile);
6905 fprintf(outfile,")\n");
6906 ast_print(tree->left,outfile,indent+2);
6908 /*------------------------------------------------------------------*/
6909 /*----------------------------*/
6911 /*----------------------------*/
6913 fprintf(outfile,"RRC (%p) type (",tree);
6914 printTypeChain(tree->ftype,outfile);
6915 fprintf(outfile,")\n");
6916 ast_print(tree->left,outfile,indent+2);
6920 fprintf(outfile,"RLC (%p) type (",tree);
6921 printTypeChain(tree->ftype,outfile);
6922 fprintf(outfile,")\n");
6923 ast_print(tree->left,outfile,indent+2);
6926 fprintf(outfile,"SWAP (%p) type (",tree);
6927 printTypeChain(tree->ftype,outfile);
6928 fprintf(outfile,")\n");
6929 ast_print(tree->left,outfile,indent+2);
6932 fprintf(outfile,"GETHBIT (%p) type (",tree);
6933 printTypeChain(tree->ftype,outfile);
6934 fprintf(outfile,")\n");
6935 ast_print(tree->left,outfile,indent+2);
6938 fprintf(outfile,"GETABIT (%p) type (",tree);
6939 printTypeChain(tree->ftype,outfile);
6940 fprintf(outfile,")\n");
6941 ast_print(tree->left,outfile,indent+2);
6942 ast_print(tree->right,outfile,indent+2);
6945 fprintf(outfile,"GETBYTE (%p) type (",tree);
6946 printTypeChain(tree->ftype,outfile);
6947 fprintf(outfile,")\n");
6948 ast_print(tree->left,outfile,indent+2);
6949 ast_print(tree->right,outfile,indent+2);
6952 fprintf(outfile,"GETWORD (%p) type (",tree);
6953 printTypeChain(tree->ftype,outfile);
6954 fprintf(outfile,")\n");
6955 ast_print(tree->left,outfile,indent+2);
6956 ast_print(tree->right,outfile,indent+2);
6959 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6960 printTypeChain(tree->ftype,outfile);
6961 fprintf(outfile,")\n");
6962 ast_print(tree->left,outfile,indent+2);
6963 ast_print(tree->right,outfile,indent+2);
6966 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6967 printTypeChain(tree->ftype,outfile);
6968 fprintf(outfile,")\n");
6969 ast_print(tree->left,outfile,indent+2);
6970 ast_print(tree->right,outfile,indent+2);
6972 /*------------------------------------------------------------------*/
6973 /*----------------------------*/
6975 /*----------------------------*/
6976 case CAST: /* change the type */
6977 fprintf(outfile,"CAST (%p) from type (",tree);
6978 printTypeChain(tree->right->ftype,outfile);
6979 fprintf(outfile,") to type (");
6980 printTypeChain(tree->ftype,outfile);
6981 fprintf(outfile,")\n");
6982 ast_print(tree->right,outfile,indent+2);
6986 fprintf(outfile,"ANDAND (%p) type (",tree);
6987 printTypeChain(tree->ftype,outfile);
6988 fprintf(outfile,")\n");
6989 ast_print(tree->left,outfile,indent+2);
6990 ast_print(tree->right,outfile,indent+2);
6993 fprintf(outfile,"OROR (%p) type (",tree);
6994 printTypeChain(tree->ftype,outfile);
6995 fprintf(outfile,")\n");
6996 ast_print(tree->left,outfile,indent+2);
6997 ast_print(tree->right,outfile,indent+2);
7000 /*------------------------------------------------------------------*/
7001 /*----------------------------*/
7002 /* comparison operators */
7003 /*----------------------------*/
7005 fprintf(outfile,"GT(>) (%p) type (",tree);
7006 printTypeChain(tree->ftype,outfile);
7007 fprintf(outfile,")\n");
7008 ast_print(tree->left,outfile,indent+2);
7009 ast_print(tree->right,outfile,indent+2);
7012 fprintf(outfile,"LT(<) (%p) type (",tree);
7013 printTypeChain(tree->ftype,outfile);
7014 fprintf(outfile,")\n");
7015 ast_print(tree->left,outfile,indent+2);
7016 ast_print(tree->right,outfile,indent+2);
7019 fprintf(outfile,"LE(<=) (%p) type (",tree);
7020 printTypeChain(tree->ftype,outfile);
7021 fprintf(outfile,")\n");
7022 ast_print(tree->left,outfile,indent+2);
7023 ast_print(tree->right,outfile,indent+2);
7026 fprintf(outfile,"GE(>=) (%p) type (",tree);
7027 printTypeChain(tree->ftype,outfile);
7028 fprintf(outfile,")\n");
7029 ast_print(tree->left,outfile,indent+2);
7030 ast_print(tree->right,outfile,indent+2);
7033 fprintf(outfile,"EQ(==) (%p) type (",tree);
7034 printTypeChain(tree->ftype,outfile);
7035 fprintf(outfile,")\n");
7036 ast_print(tree->left,outfile,indent+2);
7037 ast_print(tree->right,outfile,indent+2);
7040 fprintf(outfile,"NE(!=) (%p) type (",tree);
7041 printTypeChain(tree->ftype,outfile);
7042 fprintf(outfile,")\n");
7043 ast_print(tree->left,outfile,indent+2);
7044 ast_print(tree->right,outfile,indent+2);
7045 /*------------------------------------------------------------------*/
7046 /*----------------------------*/
7048 /*----------------------------*/
7049 case SIZEOF: /* evaluate wihout code generation */
7050 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7053 /*------------------------------------------------------------------*/
7054 /*----------------------------*/
7055 /* conditional operator '?' */
7056 /*----------------------------*/
7058 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7059 printTypeChain(tree->ftype,outfile);
7060 fprintf(outfile,")\n");
7061 ast_print(tree->left,outfile,indent+2);
7062 ast_print(tree->right,outfile,indent+2);
7066 fprintf(outfile,"COLON(:) (%p) type (",tree);
7067 printTypeChain(tree->ftype,outfile);
7068 fprintf(outfile,")\n");
7069 ast_print(tree->left,outfile,indent+2);
7070 ast_print(tree->right,outfile,indent+2);
7073 /*------------------------------------------------------------------*/
7074 /*----------------------------*/
7075 /* assignment operators */
7076 /*----------------------------*/
7078 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7079 printTypeChain(tree->ftype,outfile);
7080 fprintf(outfile,")\n");
7081 ast_print(tree->left,outfile,indent+2);
7082 ast_print(tree->right,outfile,indent+2);
7085 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7086 printTypeChain(tree->ftype,outfile);
7087 fprintf(outfile,")\n");
7088 ast_print(tree->left,outfile,indent+2);
7089 ast_print(tree->right,outfile,indent+2);
7092 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7093 printTypeChain(tree->ftype,outfile);
7094 fprintf(outfile,")\n");
7095 ast_print(tree->left,outfile,indent+2);
7096 ast_print(tree->right,outfile,indent+2);
7099 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7100 printTypeChain(tree->ftype,outfile);
7101 fprintf(outfile,")\n");
7102 ast_print(tree->left,outfile,indent+2);
7103 ast_print(tree->right,outfile,indent+2);
7106 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7107 printTypeChain(tree->ftype,outfile);
7108 fprintf(outfile,")\n");
7109 ast_print(tree->left,outfile,indent+2);
7110 ast_print(tree->right,outfile,indent+2);
7113 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7114 printTypeChain(tree->ftype,outfile);
7115 fprintf(outfile,")\n");
7116 ast_print(tree->left,outfile,indent+2);
7117 ast_print(tree->right,outfile,indent+2);
7120 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7121 printTypeChain(tree->ftype,outfile);
7122 fprintf(outfile,")\n");
7123 ast_print(tree->left,outfile,indent+2);
7124 ast_print(tree->right,outfile,indent+2);
7126 /*------------------------------------------------------------------*/
7127 /*----------------------------*/
7129 /*----------------------------*/
7131 fprintf(outfile,"SUBASS(-=) (%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,"ADDASS(+=) (%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 /*----------------------------*/
7150 /* straight assignemnt */
7151 /*----------------------------*/
7153 fprintf(outfile,"ASSIGN(=) (%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 /* comma operator */
7162 /*----------------------------*/
7164 fprintf(outfile,"COMMA(,) (%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 /*----------------------------*/
7173 /*----------------------------*/
7176 fprintf(outfile,"CALL (%p) type (",tree);
7177 printTypeChain(tree->ftype,outfile);
7178 fprintf(outfile,")\n");
7179 ast_print(tree->left,outfile,indent+2);
7180 ast_print(tree->right,outfile,indent+2);
7183 fprintf(outfile,"PARMS\n");
7184 ast_print(tree->left,outfile,indent+2);
7185 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7186 ast_print(tree->right,outfile,indent+2);
7189 /*------------------------------------------------------------------*/
7190 /*----------------------------*/
7191 /* return statement */
7192 /*----------------------------*/
7194 fprintf(outfile,"RETURN (%p) type (",tree);
7196 printTypeChain(tree->right->ftype,outfile);
7198 fprintf(outfile,")\n");
7199 ast_print(tree->right,outfile,indent+2);
7201 /*------------------------------------------------------------------*/
7202 /*----------------------------*/
7203 /* label statement */
7204 /*----------------------------*/
7206 fprintf(outfile,"LABEL (%p)\n",tree);
7207 ast_print(tree->left,outfile,indent+2);
7208 ast_print(tree->right,outfile,indent);
7210 /*------------------------------------------------------------------*/
7211 /*----------------------------*/
7212 /* switch statement */
7213 /*----------------------------*/
7217 fprintf(outfile,"SWITCH (%p) ",tree);
7218 ast_print(tree->left,outfile,0);
7219 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7220 INDENT(indent+2,outfile);
7221 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7222 (int) ulFromVal(val),
7223 tree->values.switchVals.swNum,
7224 (int) ulFromVal(val));
7226 ast_print(tree->right,outfile,indent);
7229 /*------------------------------------------------------------------*/
7230 /*----------------------------*/
7232 /*----------------------------*/
7234 fprintf(outfile,"IF (%p) \n",tree);
7235 ast_print(tree->left,outfile,indent+2);
7236 if (tree->trueLabel) {
7237 INDENT(indent+2,outfile);
7238 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7240 if (tree->falseLabel) {
7241 INDENT(indent+2,outfile);
7242 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7244 ast_print(tree->right,outfile,indent+2);
7246 /*----------------------------*/
7247 /* goto Statement */
7248 /*----------------------------*/
7250 fprintf(outfile,"GOTO (%p) \n",tree);
7251 ast_print(tree->left,outfile,indent+2);
7252 fprintf(outfile,"\n");
7254 /*------------------------------------------------------------------*/
7255 /*----------------------------*/
7257 /*----------------------------*/
7259 fprintf(outfile,"FOR (%p) \n",tree);
7260 if (AST_FOR( tree, initExpr)) {
7261 INDENT(indent+2,outfile);
7262 fprintf(outfile,"INIT EXPR ");
7263 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7265 if (AST_FOR( tree, condExpr)) {
7266 INDENT(indent+2,outfile);
7267 fprintf(outfile,"COND EXPR ");
7268 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7270 if (AST_FOR( tree, loopExpr)) {
7271 INDENT(indent+2,outfile);
7272 fprintf(outfile,"LOOP EXPR ");
7273 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7275 fprintf(outfile,"FOR LOOP BODY \n");
7276 ast_print(tree->left,outfile,indent+2);
7279 fprintf(outfile,"CRITICAL (%p) \n",tree);
7280 ast_print(tree->left,outfile,indent+2);
7288 ast_print(t,stdout,0);
7291 /*-----------------------------------------------------------------*/
7292 /* astErrors : returns non-zero if errors present in tree */
7293 /*-----------------------------------------------------------------*/
7294 int astErrors(ast *t)
7303 if (t->type == EX_VALUE
7304 && t->opval.val->sym
7305 && t->opval.val->sym->undefined)
7308 errors += astErrors(t->left);
7309 errors += astErrors(t->right);