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);
546 /* if this is a label resolve it from the labelTab */
547 if (IS_AST_VALUE (tree) &&
548 tree->opval.val->sym &&
549 tree->opval.val->sym->islbl)
552 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
553 tree->opval.val->sym->name);
556 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
557 tree->opval.val->sym->name);
559 tree->opval.val->sym = csym;
561 goto resolveChildren;
564 /* do only for leafs */
565 if (IS_AST_VALUE (tree) &&
566 tree->opval.val->sym &&
567 !tree->opval.val->sym->implicit)
570 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
572 /* if found in the symbol table & they are not the same */
573 if (csym && tree->opval.val->sym != csym)
575 tree->opval.val->sym = csym;
576 tree->opval.val->type = csym->type;
577 tree->opval.val->etype = csym->etype;
580 /* if not found in the symbol table */
581 /* mark it as undefined & assume it */
582 /* is an integer in data space */
583 if (!csym && !tree->opval.val->sym->implicit)
586 /* if this is a function name then */
587 /* mark it as returning an int */
590 tree->opval.val->sym->type = newLink (DECLARATOR);
591 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
592 tree->opval.val->sym->type->next =
593 tree->opval.val->sym->etype = newIntLink ();
594 tree->opval.val->etype = tree->opval.val->etype;
595 tree->opval.val->type = tree->opval.val->sym->type;
596 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
597 tree->opval.val->sym->name);
598 //tree->opval.val->sym->undefined = 1;
599 allocVariables (tree->opval.val->sym);
603 tree->opval.val->sym->undefined = 1;
604 tree->opval.val->type =
605 tree->opval.val->etype = newIntLink ();
606 tree->opval.val->sym->type =
607 tree->opval.val->sym->etype = newIntLink ();
613 resolveSymbols (tree->left);
614 resolveSymbols (tree->right);
619 /*------------------------------------------------------------------------*/
620 /* setAstFileLine - walks a ast tree & sets the file name and line number */
621 /*------------------------------------------------------------------------*/
622 int setAstFileLine (ast * tree, char *filename, int lineno)
627 tree->filename = filename;
628 tree->lineno = lineno;
629 setAstFileLine (tree->left, filename, lineno);
630 setAstFileLine (tree->right, filename, lineno);
634 /*-----------------------------------------------------------------*/
635 /* funcOfType :- function of type with name */
636 /*-----------------------------------------------------------------*/
638 funcOfType (char *name, sym_link * type, sym_link * argType,
642 /* create the symbol */
643 sym = newSymbol (name, 0);
645 /* setup return value */
646 sym->type = newLink (DECLARATOR);
647 DCL_TYPE (sym->type) = FUNCTION;
648 sym->type->next = copyLinkChain (type);
649 sym->etype = getSpec (sym->type);
650 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
652 /* if arguments required */
656 args = FUNC_ARGS(sym->type) = newValue ();
660 args->type = copyLinkChain (argType);
661 args->etype = getSpec (args->type);
662 SPEC_EXTR(args->etype)=1;
665 args = args->next = newValue ();
672 allocVariables (sym);
677 /*-----------------------------------------------------------------*/
678 /* funcOfTypeVarg :- function of type with name and argtype */
679 /*-----------------------------------------------------------------*/
681 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
686 /* create the symbol */
687 sym = newSymbol (name, 0);
689 /* setup return value */
690 sym->type = newLink (DECLARATOR);
691 DCL_TYPE (sym->type) = FUNCTION;
692 sym->type->next = typeFromStr(rtype);
693 sym->etype = getSpec (sym->type);
695 /* if arguments required */
698 args = FUNC_ARGS(sym->type) = newValue ();
700 for ( i = 0 ; i < nArgs ; i++ ) {
701 args->type = typeFromStr(atypes[i]);
702 args->etype = getSpec (args->type);
703 SPEC_EXTR(args->etype)=1;
704 if ((i + 1) == nArgs) break;
705 args = args->next = newValue ();
712 allocVariables (sym);
717 /*-----------------------------------------------------------------*/
718 /* reverseParms - will reverse a parameter tree */
719 /*-----------------------------------------------------------------*/
721 reverseParms (ast * ptree)
727 /* top down if we find a nonParm tree then quit */
728 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
730 /* The various functions expect the parameter tree to be right heavy. */
731 /* Rotate the tree to be left heavy so that after reversal it is */
732 /* right heavy again. */
733 while ((ttree = ptree->right) && ttree->type == EX_OP &&
734 ttree->opval.op == PARAM)
736 ptree->right = ttree->right;
737 ttree->right = ttree->left;
738 ttree->left = ptree->left;
744 ptree->left = ptree->right;
745 ptree->right = ttree;
747 reverseParms (ptree->left);
748 reverseParms (ptree->right);
754 /*-----------------------------------------------------------------*/
755 /* processParms - makes sure the parameters are okay and do some */
756 /* processing with them */
757 /*-----------------------------------------------------------------*/
759 processParms (ast *func,
762 int *parmNumber, /* unused, although updated */
765 RESULT_TYPE resultType;
768 /* if none of them exist */
769 if (!defParm && !*actParm)
774 if (getenv("DEBUG_SANITY"))
776 fprintf (stderr, "processParms: %s ", defParm->name);
778 /* make sure the type is complete and sane */
779 checkTypeSanity(defParm->etype, defParm->name);
782 if (IS_CODEPTR (func->ftype))
783 functype = func->ftype->next;
785 functype = func->ftype;
787 /* if the function is being called via a pointer & */
788 /* it has not been defined reentrant then we cannot */
789 /* have parameters */
790 /* PIC16 port can... */
791 if (!TARGET_IS_PIC16)
793 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
795 werror (E_NONRENT_ARGS);
801 /* if defined parameters ended but actual parameters */
802 /* exist and this is not defined as a variable arg */
803 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
805 werror (E_TOO_MANY_PARMS);
809 /* if defined parameters present but no actual parameters */
810 if (defParm && !*actParm)
812 werror (E_TOO_FEW_PARMS);
816 /* if this is a PARAM node then match left & right */
817 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
819 (*actParm)->decorated = 1;
820 return (processParms (func, defParm,
821 &(*actParm)->left, parmNumber, FALSE) ||
822 processParms (func, defParm ? defParm->next : NULL,
823 &(*actParm)->right, parmNumber, rightmost));
825 else if (defParm) /* not vararg */
827 /* If we have found a value node by following only right-hand links,
828 * then we know that there are no more values after us.
830 * Therefore, if there are more defined parameters, the caller didn't
833 if (rightmost && defParm->next)
835 werror (E_TOO_FEW_PARMS);
840 /* decorate parameter */
841 resultType = defParm ? getResultTypeFromType (defParm->type) :
843 *actParm = decorateType (*actParm, resultType);
845 if (IS_VOID((*actParm)->ftype))
847 werror (E_VOID_VALUE_USED);
851 /* If this is a varargs function... */
852 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
857 /* don't perform integer promotion of explicitly typecasted variable arguments
858 * if sdcc extensions are enabled */
859 if (options.std_sdcc &&
860 (IS_CAST_OP (*actParm) ||
861 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
862 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
864 /* Parameter was explicitly typecast; don't touch it. */
868 ftype = (*actParm)->ftype;
870 /* If it's a char, upcast to int. */
871 if (IS_INTEGRAL (ftype)
872 && (getSize (ftype) < (unsigned) INTSIZE))
874 newType = newAst_LINK(INTTYPE);
877 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
879 newType = newAst_LINK (copyLinkChain(ftype));
880 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
883 if (IS_AGGREGATE (ftype))
885 newType = newAst_LINK (copyLinkChain (ftype));
886 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
891 /* cast required; change this op to a cast. */
892 (*actParm)->decorated = 0;
893 *actParm = newNode (CAST, newType, *actParm);
894 (*actParm)->filename = (*actParm)->right->filename;
895 (*actParm)->lineno = (*actParm)->right->lineno;
897 decorateType (*actParm, RESULT_TYPE_NONE);
902 /* if defined parameters ended but actual has not & */
904 if (!defParm && *actParm &&
905 (options.stackAuto || IFFUNC_ISREENT (functype)))
908 resolveSymbols (*actParm);
910 /* the parameter type must be at least castable */
911 if (compareType (defParm->type, (*actParm)->ftype) == 0)
913 werror (E_INCOMPAT_TYPES);
914 printFromToType ((*actParm)->ftype, defParm->type);
918 /* if the parameter is castable then add the cast */
919 if (compareType (defParm->type, (*actParm)->ftype) < 0)
923 resultType = getResultTypeFromType (defParm->etype);
924 pTree = resolveSymbols (copyAst (*actParm));
926 /* now change the current one to a cast */
927 (*actParm)->type = EX_OP;
928 (*actParm)->opval.op = CAST;
929 (*actParm)->left = newAst_LINK (defParm->type);
930 (*actParm)->right = pTree;
931 (*actParm)->decorated = 0; /* force typechecking */
932 decorateType (*actParm, resultType);
935 /* make a copy and change the regparm type to the defined parm */
936 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
937 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
938 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
940 /* if the function is being called via a pointer & */
941 /* this parameter is not passed in registers */
942 /* then the function must be defined reentrant */
943 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
944 !IFFUNC_ISREENT (functype) && !options.stackAuto)
946 werror (E_NONRENT_ARGS);
955 /*-----------------------------------------------------------------*/
956 /* createIvalType - generates ival for basic types */
957 /*-----------------------------------------------------------------*/
959 createIvalType (ast * sym, sym_link * type, initList * ilist)
963 /* if initList is deep */
964 if (ilist->type == INIT_DEEP)
965 ilist = ilist->init.deep;
967 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
968 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
971 /*-----------------------------------------------------------------*/
972 /* createIvalStruct - generates initial value for structures */
973 /*-----------------------------------------------------------------*/
975 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
982 sflds = SPEC_STRUCT (type)->fields;
983 if (ilist->type != INIT_DEEP)
985 werror (E_INIT_STRUCT, "");
989 iloop = ilist->init.deep;
991 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
993 /* if we have come to end */
997 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
998 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
999 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
1000 iloop, rast, rootValue)),
1007 if (IS_AST_VALUE (sym))
1008 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1009 W_EXCESS_INITIALIZERS, "struct",
1010 sym->opval.val->sym->name);
1012 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1019 /*-----------------------------------------------------------------*/
1020 /* createIvalArray - generates code for array initialization */
1021 /*-----------------------------------------------------------------*/
1023 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1027 int lcnt = 0, size = 0;
1028 literalList *literalL;
1030 /* take care of the special case */
1031 /* array of characters can be init */
1033 if (IS_CHAR (type->next))
1034 if ((rast = createIvalCharPtr (sym,
1036 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1039 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1041 /* not the special case */
1042 if (ilist->type != INIT_DEEP)
1044 werror (E_INIT_STRUCT, "");
1048 iloop = ilist->init.deep;
1049 lcnt = DCL_ELEM (type);
1051 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1055 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1057 rast = newNode(ARRAYINIT, aSym, NULL);
1058 rast->values.constlist = literalL;
1060 // Make sure size is set to length of initializer list.
1064 iloop = iloop->next;
1067 if (lcnt && size > lcnt)
1069 // Array size was specified, and we have more initializers than needed.
1070 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1071 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1080 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1081 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1082 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1083 iloop = (iloop ? iloop->next : NULL);
1089 /* no of elements given and we */
1090 /* have generated for all of them */
1093 // is this a better way? at least it won't crash
1094 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1095 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1102 /* if we have not been given a size */
1103 if (!DCL_ELEM (type))
1105 /* check, if it's a flexible array */
1106 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1107 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1109 DCL_ELEM (type) = size;
1112 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1116 /*-----------------------------------------------------------------*/
1117 /* createIvalCharPtr - generates initial values for char pointers */
1118 /*-----------------------------------------------------------------*/
1120 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1125 /* if this is a pointer & right is a literal array then */
1126 /* just assignment will do */
1127 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1128 SPEC_SCLS (iexpr->etype) == S_CODE)
1129 && IS_ARRAY (iexpr->ftype)))
1130 return newNode ('=', sym, iexpr);
1132 /* left side is an array so we have to assign each element */
1133 if ((IS_LITERAL (iexpr->etype) ||
1134 SPEC_SCLS (iexpr->etype) == S_CODE)
1135 && IS_ARRAY (iexpr->ftype))
1137 /* for each character generate an assignment */
1138 /* to the array element */
1139 char *s = SPEC_CVAL (iexpr->etype).v_char;
1141 unsigned int symsize = getSize (type);
1143 size = getSize (iexpr->ftype);
1144 if (symsize && size>symsize)
1146 if (size>(symsize+1))
1148 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1150 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1156 for (i=0;i<size;i++)
1158 rast = newNode (NULLOP,
1162 newAst_VALUE (valueFromLit ((float) i))),
1163 newAst_VALUE (valueFromLit (*s))));
1167 // now WE don't need iexpr's symbol anymore
1168 freeStringSymbol(AST_SYMBOL(iexpr));
1170 /* if we have not been given a size */
1171 if (!DCL_ELEM (type))
1173 /* check, if it's a flexible array */
1174 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1175 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1177 DCL_ELEM (type) = size;
1180 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1186 /*-----------------------------------------------------------------*/
1187 /* createIvalPtr - generates initial value for pointers */
1188 /*-----------------------------------------------------------------*/
1190 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1196 if (ilist->type == INIT_DEEP)
1197 ilist = ilist->init.deep;
1199 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1201 /* if character pointer */
1202 if (IS_CHAR (type->next))
1203 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1206 return newNode ('=', sym, iexpr);
1209 /*-----------------------------------------------------------------*/
1210 /* createIval - generates code for initial value */
1211 /*-----------------------------------------------------------------*/
1213 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1220 /* if structure then */
1221 if (IS_STRUCT (type))
1222 rast = createIvalStruct (sym, type, ilist, rootValue);
1224 /* if this is a pointer */
1226 rast = createIvalPtr (sym, type, ilist, rootValue);
1228 /* if this is an array */
1229 if (IS_ARRAY (type))
1230 rast = createIvalArray (sym, type, ilist, rootValue);
1232 /* if type is SPECIFIER */
1234 rast = createIvalType (sym, type, ilist);
1237 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1239 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1242 /*-----------------------------------------------------------------*/
1243 /* initAggregates - initialises aggregate variables with initv */
1244 /*-----------------------------------------------------------------*/
1245 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1246 ast *newAst = newAst_VALUE (symbolVal (sym));
1247 return createIval (newAst, sym->type, ival, wid, newAst);
1250 /*-----------------------------------------------------------------*/
1251 /* gatherAutoInit - creates assignment expressions for initial */
1253 /*-----------------------------------------------------------------*/
1255 gatherAutoInit (symbol * autoChain)
1262 for (sym = autoChain; sym; sym = sym->next)
1265 /* resolve the symbols in the ival */
1267 resolveIvalSym (sym->ival, sym->type);
1270 /* if we are PIC16 port,
1271 * and this is a static,
1272 * and have initial value,
1273 * and not S_CODE, don't emit in gs segment,
1274 * but allow glue.c:pic16emitRegularMap to put symbol
1275 * in idata section */
1276 if(TARGET_IS_PIC16 &&
1277 IS_STATIC (sym->etype) && sym->ival
1278 && SPEC_SCLS(sym->etype) != S_CODE) {
1279 SPEC_SCLS (sym->etype) = S_DATA;
1284 /* if this is a static variable & has an */
1285 /* initial value the code needs to be lifted */
1286 /* here to the main portion since they can be */
1287 /* initialised only once at the start */
1288 if (IS_STATIC (sym->etype) && sym->ival &&
1289 SPEC_SCLS (sym->etype) != S_CODE)
1293 /* insert the symbol into the symbol table */
1294 /* with level = 0 & name = rname */
1295 newSym = copySymbol (sym);
1296 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1298 /* now lift the code to main */
1299 if (IS_AGGREGATE (sym->type)) {
1300 work = initAggregates (sym, sym->ival, NULL);
1302 if (getNelements(sym->type, sym->ival)>1) {
1303 werrorfl (sym->fileDef, sym->lineDef,
1304 W_EXCESS_INITIALIZERS, "scalar",
1307 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1308 list2expr (sym->ival));
1311 setAstFileLine (work, sym->fileDef, sym->lineDef);
1315 staticAutos = newNode (NULLOP, staticAutos, work);
1322 /* if there is an initial value */
1323 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1325 initList *ilist=sym->ival;
1327 while (ilist->type == INIT_DEEP) {
1328 ilist = ilist->init.deep;
1331 /* update lineno for error msg */
1332 filename = sym->fileDef;
1333 lineno = sym->lineDef;
1334 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1336 if (IS_AGGREGATE (sym->type)) {
1337 work = initAggregates (sym, sym->ival, NULL);
1339 if (getNelements(sym->type, sym->ival)>1) {
1340 werrorfl (sym->fileDef, sym->lineDef,
1341 W_EXCESS_INITIALIZERS, "scalar",
1344 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1345 list2expr (sym->ival));
1349 setAstFileLine (work, sym->fileDef, sym->lineDef);
1353 init = newNode (NULLOP, init, work);
1362 /*-----------------------------------------------------------------*/
1363 /* freeStringSymbol - delete a literal string if no more usage */
1364 /*-----------------------------------------------------------------*/
1365 void freeStringSymbol(symbol *sym) {
1366 /* make sure this is a literal string */
1367 assert (sym->isstrlit);
1368 if (--sym->isstrlit == 0) { // lower the usage count
1369 memmap *segment=SPEC_OCLS(sym->etype);
1371 deleteSetItem(&segment->syms, sym);
1376 /*-----------------------------------------------------------------*/
1377 /* stringToSymbol - creates a symbol from a literal string */
1378 /*-----------------------------------------------------------------*/
1380 stringToSymbol (value * val)
1382 char name[SDCC_NAME_MAX + 1];
1383 static int charLbl = 0;
1388 // have we heard this before?
1389 for (sp = statsg->syms; sp; sp = sp->next)
1392 size = getSize (sym->type);
1393 if (sym->isstrlit && size == getSize (val->type) &&
1394 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1396 // yes, this is old news. Don't publish it again.
1397 sym->isstrlit++; // but raise the usage count
1398 return symbolVal (sym);
1402 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1403 sym = newSymbol (name, 0); /* make it @ level 0 */
1404 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1406 /* copy the type from the value passed */
1407 sym->type = copyLinkChain (val->type);
1408 sym->etype = getSpec (sym->type);
1409 /* change to storage class & output class */
1410 SPEC_SCLS (sym->etype) = S_CODE;
1411 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1412 SPEC_STAT (sym->etype) = 1;
1413 /* make the level & block = 0 */
1414 sym->block = sym->level = 0;
1416 /* create an ival */
1417 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1422 allocVariables (sym);
1425 return symbolVal (sym);
1429 /*-----------------------------------------------------------------*/
1430 /* processBlockVars - will go thru the ast looking for block if */
1431 /* a block is found then will allocate the syms */
1432 /* will also gather the auto inits present */
1433 /*-----------------------------------------------------------------*/
1435 processBlockVars (ast * tree, int *stack, int action)
1440 /* if this is a block */
1441 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1445 if (action == ALLOCATE)
1447 *stack += allocVariables (tree->values.sym);
1448 autoInit = gatherAutoInit (tree->values.sym);
1450 /* if there are auto inits then do them */
1452 tree->left = newNode (NULLOP, autoInit, tree->left);
1454 else /* action is deallocate */
1455 deallocLocal (tree->values.sym);
1458 processBlockVars (tree->left, stack, action);
1459 processBlockVars (tree->right, stack, action);
1464 /*-------------------------------------------------------------*/
1465 /* constExprTree - returns TRUE if this tree is a constant */
1467 /*-------------------------------------------------------------*/
1468 bool constExprTree (ast *cexpr) {
1474 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1476 switch (cexpr->type)
1479 if (IS_AST_LIT_VALUE(cexpr)) {
1480 // this is a literal
1483 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1484 // a function's address will never change
1487 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1488 // an array's address will never change
1491 if (IS_AST_SYM_VALUE(cexpr) &&
1492 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1493 // a symbol in code space will never change
1494 // This is only for the 'char *s="hallo"' case and will have to leave
1495 //printf(" code space symbol");
1500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501 "unexpected link in expression tree\n");
1504 if (cexpr->opval.op==ARRAYINIT) {
1505 // this is a list of literals
1508 if (cexpr->opval.op=='=') {
1509 return constExprTree(cexpr->right);
1511 if (cexpr->opval.op==CAST) {
1512 // cast ignored, maybe we should throw a warning here?
1513 return constExprTree(cexpr->right);
1515 if (cexpr->opval.op=='&') {
1518 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1521 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1526 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1531 /*-----------------------------------------------------------------*/
1532 /* constExprValue - returns the value of a constant expression */
1533 /* or NULL if it is not a constant expression */
1534 /*-----------------------------------------------------------------*/
1536 constExprValue (ast * cexpr, int check)
1538 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1540 /* if this is not a constant then */
1541 if (!IS_LITERAL (cexpr->ftype))
1543 /* then check if this is a literal array
1545 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1546 SPEC_CVAL (cexpr->etype).v_char &&
1547 IS_ARRAY (cexpr->ftype))
1549 value *val = valFromType (cexpr->ftype);
1550 SPEC_SCLS (val->etype) = S_LITERAL;
1551 val->sym = cexpr->opval.val->sym;
1552 val->sym->type = copyLinkChain (cexpr->ftype);
1553 val->sym->etype = getSpec (val->sym->type);
1554 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1558 /* if we are casting a literal value then */
1559 if (IS_AST_OP (cexpr) &&
1560 cexpr->opval.op == CAST &&
1561 IS_LITERAL (cexpr->right->ftype))
1563 return valCastLiteral (cexpr->ftype,
1564 floatFromVal (cexpr->right->opval.val));
1567 if (IS_AST_VALUE (cexpr))
1569 return cexpr->opval.val;
1573 werror (E_CONST_EXPECTED, "found expression");
1578 /* return the value */
1579 if (IS_AST_VALUE (cexpr))
1581 return cexpr->opval.val;
1586 /*-----------------------------------------------------------------*/
1587 /* isLabelInAst - will return true if a given label is found */
1588 /*-----------------------------------------------------------------*/
1590 isLabelInAst (symbol * label, ast * tree)
1592 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1595 if (IS_AST_OP (tree) &&
1596 tree->opval.op == LABEL &&
1597 isSymbolEqual (AST_SYMBOL (tree->left), label))
1600 return isLabelInAst (label, tree->right) &&
1601 isLabelInAst (label, tree->left);
1604 /*-----------------------------------------------------------------*/
1605 /* isLoopCountable - return true if the loop count can be determi- */
1606 /* -ned at compile time . */
1607 /*-----------------------------------------------------------------*/
1609 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1610 symbol ** sym, ast ** init, ast ** end)
1613 /* the loop is considered countable if the following
1614 conditions are true :-
1616 a) initExpr :- <sym> = <const>
1617 b) condExpr :- <sym> < <const1>
1618 c) loopExpr :- <sym> ++
1621 /* first check the initExpr */
1622 if (IS_AST_OP (initExpr) &&
1623 initExpr->opval.op == '=' && /* is assignment */
1624 IS_AST_SYM_VALUE (initExpr->left))
1625 { /* left is a symbol */
1627 *sym = AST_SYMBOL (initExpr->left);
1628 *init = initExpr->right;
1633 /* don't reverse loop with volatile counter */
1634 if (IS_VOLATILE ((*sym)->type))
1637 /* for now the symbol has to be of
1639 if (!IS_INTEGRAL ((*sym)->type))
1642 /* now check condExpr */
1643 if (IS_AST_OP (condExpr))
1646 switch (condExpr->opval.op)
1649 if (IS_AST_SYM_VALUE (condExpr->left) &&
1650 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1651 IS_AST_LIT_VALUE (condExpr->right))
1653 *end = condExpr->right;
1659 if (IS_AST_OP (condExpr->left) &&
1660 condExpr->left->opval.op == '>' &&
1661 IS_AST_LIT_VALUE (condExpr->left->right) &&
1662 IS_AST_SYM_VALUE (condExpr->left->left) &&
1663 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1666 *end = newNode ('+', condExpr->left->right,
1667 newAst_VALUE (constCharVal (1)));
1680 /* check loop expression is of the form <sym>++ */
1681 if (!IS_AST_OP (loopExpr))
1684 /* check if <sym> ++ */
1685 if (loopExpr->opval.op == INC_OP)
1691 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1692 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1699 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1700 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1708 if (loopExpr->opval.op == ADD_ASSIGN)
1711 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1712 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1713 IS_AST_LIT_VALUE (loopExpr->right) &&
1714 AST_ULONG_VALUE (loopExpr->right) != 1)
1722 /*-----------------------------------------------------------------*/
1723 /* astHasVolatile - returns true if ast contains any volatile */
1724 /*-----------------------------------------------------------------*/
1726 astHasVolatile (ast * tree)
1731 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1734 if (IS_AST_OP (tree))
1735 return astHasVolatile (tree->left) ||
1736 astHasVolatile (tree->right);
1741 /*-----------------------------------------------------------------*/
1742 /* astHasPointer - return true if the ast contains any ptr variable */
1743 /*-----------------------------------------------------------------*/
1745 astHasPointer (ast * tree)
1750 if (IS_AST_LINK (tree))
1753 /* if we hit an array expression then check
1754 only the left side */
1755 if (IS_AST_OP (tree) && tree->opval.op == '[')
1756 return astHasPointer (tree->left);
1758 if (IS_AST_VALUE (tree))
1759 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1761 return astHasPointer (tree->left) ||
1762 astHasPointer (tree->right);
1766 /*-----------------------------------------------------------------*/
1767 /* astHasSymbol - return true if the ast has the given symbol */
1768 /*-----------------------------------------------------------------*/
1770 astHasSymbol (ast * tree, symbol * sym)
1772 if (!tree || IS_AST_LINK (tree))
1775 if (IS_AST_VALUE (tree))
1777 if (IS_AST_SYM_VALUE (tree))
1778 return isSymbolEqual (AST_SYMBOL (tree), sym);
1783 return astHasSymbol (tree->left, sym) ||
1784 astHasSymbol (tree->right, sym);
1787 /*-----------------------------------------------------------------*/
1788 /* astHasDeref - return true if the ast has an indirect access */
1789 /*-----------------------------------------------------------------*/
1791 astHasDeref (ast * tree)
1793 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1796 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1798 return astHasDeref (tree->left) || astHasDeref (tree->right);
1801 /*-----------------------------------------------------------------*/
1802 /* isConformingBody - the loop body has to conform to a set of */
1803 /* rules for the loop to be considered reversible read on for rules*/
1804 /*-----------------------------------------------------------------*/
1806 isConformingBody (ast * pbody, symbol * sym, ast * body)
1809 /* we are going to do a pre-order traversal of the
1810 tree && check for the following conditions. (essentially
1811 a set of very shallow tests )
1812 a) the sym passed does not participate in any arithmetic operation
1813 b) There are no function calls
1814 c) all jumps are within the body
1815 d) address of loop control variable not taken
1816 e) if an assignment has a pointer on the left hand side make sure
1817 right does not have loop control variable
1820 /* if we reach the end or a leaf then true */
1821 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1824 /* if anything else is "volatile" */
1825 if (IS_VOLATILE (TETYPE (pbody)))
1828 /* we will walk the body in a pre-order traversal for
1830 switch (pbody->opval.op)
1832 /*------------------------------------------------------------------*/
1834 // if the loopvar is used as an index
1835 /* array op is commutative -- must check both left & right */
1836 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1839 return isConformingBody (pbody->right, sym, body)
1840 && isConformingBody (pbody->left, sym, body);
1842 /*------------------------------------------------------------------*/
1847 /*------------------------------------------------------------------*/
1851 /* sure we are not sym is not modified */
1853 IS_AST_SYM_VALUE (pbody->left) &&
1854 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1858 IS_AST_SYM_VALUE (pbody->right) &&
1859 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1864 /*------------------------------------------------------------------*/
1866 case '*': /* can be unary : if right is null then unary operation */
1871 /* if right is NULL then unary operation */
1872 /*------------------------------------------------------------------*/
1873 /*----------------------------*/
1875 /*----------------------------*/
1878 if (IS_AST_SYM_VALUE (pbody->left) &&
1879 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1882 return isConformingBody (pbody->left, sym, body);
1886 if (astHasSymbol (pbody->left, sym) ||
1887 astHasSymbol (pbody->right, sym))
1892 /*------------------------------------------------------------------*/
1903 if (IS_AST_SYM_VALUE (pbody->left) &&
1904 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1907 if (IS_AST_SYM_VALUE (pbody->right) &&
1908 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1911 return isConformingBody (pbody->left, sym, body) &&
1912 isConformingBody (pbody->right, sym, body);
1920 if (IS_AST_SYM_VALUE (pbody->left) &&
1921 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1923 return isConformingBody (pbody->left, sym, body);
1925 /*------------------------------------------------------------------*/
1937 case SIZEOF: /* evaluate wihout code generation */
1939 if (IS_AST_SYM_VALUE (pbody->left) &&
1940 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1943 if (IS_AST_SYM_VALUE (pbody->right) &&
1944 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1947 return isConformingBody (pbody->left, sym, body) &&
1948 isConformingBody (pbody->right, sym, body);
1950 /*------------------------------------------------------------------*/
1953 /* if left has a pointer & right has loop
1954 control variable then we cannot */
1955 if (astHasPointer (pbody->left) &&
1956 astHasSymbol (pbody->right, sym))
1958 if (astHasVolatile (pbody->left))
1961 if (IS_AST_SYM_VALUE (pbody->left)) {
1962 // if the loopvar has an assignment
1963 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1965 // if the loopvar is used in another (maybe conditional) block
1966 if (astHasSymbol (pbody->right, sym) &&
1967 (pbody->level >= body->level)) {
1972 if (astHasVolatile (pbody->left))
1975 if (astHasDeref(pbody->right))
1978 return isConformingBody (pbody->left, sym, body) &&
1979 isConformingBody (pbody->right, sym, body);
1990 assert ("Parser should not have generated this\n");
1992 /*------------------------------------------------------------------*/
1993 /*----------------------------*/
1994 /* comma operator */
1995 /*----------------------------*/
1997 return isConformingBody (pbody->left, sym, body) &&
1998 isConformingBody (pbody->right, sym, body);
2000 /*------------------------------------------------------------------*/
2001 /*----------------------------*/
2003 /*----------------------------*/
2005 /* if local & not passed as parameter &
2006 not used to find the function then ok */
2007 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2008 !astHasSymbol (pbody->left, sym))
2014 /*------------------------------------------------------------------*/
2015 /*----------------------------*/
2016 /* return statement */
2017 /*----------------------------*/
2022 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2027 if (astHasSymbol (pbody->left, sym))
2034 return isConformingBody (pbody->left, sym, body) &&
2035 isConformingBody (pbody->right, sym, body);
2038 /*-----------------------------------------------------------------*/
2039 /* isLoopReversible - takes a for loop as input && returns true */
2040 /* if the for loop is reversible. If yes will set the value of */
2041 /* the loop control var & init value & termination value */
2042 /*-----------------------------------------------------------------*/
2044 isLoopReversible (ast * loop, symbol ** loopCntrl,
2045 ast ** init, ast ** end)
2047 /* if option says don't do it then don't */
2048 if (optimize.noLoopReverse)
2050 /* there are several tests to determine this */
2052 /* for loop has to be of the form
2053 for ( <sym> = <const1> ;
2054 [<sym> < <const2>] ;
2055 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2057 if (!isLoopCountable (AST_FOR (loop, initExpr),
2058 AST_FOR (loop, condExpr),
2059 AST_FOR (loop, loopExpr),
2060 loopCntrl, init, end))
2063 /* now do some serious checking on the body of the loop
2066 return isConformingBody (loop->left, *loopCntrl, loop->left);
2070 /*-----------------------------------------------------------------*/
2071 /* replLoopSym - replace the loop sym by loop sym -1 */
2072 /*-----------------------------------------------------------------*/
2074 replLoopSym (ast * body, symbol * sym)
2077 if (!body || IS_AST_LINK (body))
2080 if (IS_AST_SYM_VALUE (body))
2083 if (isSymbolEqual (AST_SYMBOL (body), sym))
2087 body->opval.op = '-';
2088 body->left = newAst_VALUE (symbolVal (sym));
2089 body->right = newAst_VALUE (constCharVal (1));
2097 replLoopSym (body->left, sym);
2098 replLoopSym (body->right, sym);
2102 /*-----------------------------------------------------------------*/
2103 /* reverseLoop - do the actual loop reversal */
2104 /*-----------------------------------------------------------------*/
2106 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2110 /* create the following tree
2115 if (sym) goto for_continue ;
2118 /* put it together piece by piece */
2119 rloop = newNode (NULLOP,
2120 createIf (newAst_VALUE (symbolVal (sym)),
2122 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2125 newAst_VALUE (symbolVal (sym)),
2128 replLoopSym (loop->left, sym);
2129 setAstFileLine (rloop, init->filename, init->lineno);
2131 rloop = newNode (NULLOP,
2133 newAst_VALUE (symbolVal (sym)),
2134 newNode ('-', end, init)),
2135 createLabel (AST_FOR (loop, continueLabel),
2139 newNode (SUB_ASSIGN,
2140 newAst_VALUE (symbolVal (sym)),
2141 newAst_VALUE (constCharVal (1))),
2144 rloop->lineno=init->lineno;
2145 return decorateType (rloop, RESULT_TYPE_NONE);
2149 /*-----------------------------------------------------------------*/
2150 /* searchLitOp - search tree (*ops only) for an ast with literal */
2151 /*-----------------------------------------------------------------*/
2153 searchLitOp (ast *tree, ast **parent, const char *ops)
2157 if (tree && optimize.global_cse)
2159 /* is there a literal operand? */
2161 IS_AST_OP(tree->right) &&
2162 tree->right->right &&
2163 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2165 if (IS_LITERAL (RTYPE (tree->right)) !=
2166 IS_LITERAL (LTYPE (tree->right)))
2168 tree->right->decorated = 0;
2169 tree->decorated = 0;
2173 ret = searchLitOp (tree->right, parent, ops);
2178 IS_AST_OP(tree->left) &&
2179 tree->left->right &&
2180 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2182 if (IS_LITERAL (RTYPE (tree->left)) !=
2183 IS_LITERAL (LTYPE (tree->left)))
2185 tree->left->decorated = 0;
2186 tree->decorated = 0;
2190 ret = searchLitOp (tree->left, parent, ops);
2198 /*-----------------------------------------------------------------*/
2199 /* getResultFromType */
2200 /*-----------------------------------------------------------------*/
2202 getResultTypeFromType (sym_link *type)
2204 /* type = getSpec (type); */
2206 return RESULT_TYPE_BIT;
2207 if (IS_BITFIELD (type))
2209 int blen = SPEC_BLEN (type);
2212 return RESULT_TYPE_BIT;
2214 return RESULT_TYPE_CHAR;
2215 return RESULT_TYPE_INT;
2218 return RESULT_TYPE_CHAR;
2219 if (IS_INT (type) && !IS_LONG (type))
2220 return RESULT_TYPE_INT;
2221 return RESULT_TYPE_OTHER;
2224 /*-----------------------------------------------------------------*/
2225 /* addCast - adds casts to a type specified by RESULT_TYPE */
2226 /*-----------------------------------------------------------------*/
2228 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2231 bool upCasted = FALSE;
2235 case RESULT_TYPE_NONE:
2236 /* if thing smaller than int must be promoted to int */
2238 getSize (tree->etype) >= INTSIZE)
2239 /* promotion not necessary or already an int */
2241 /* char and bits: promote to int */
2242 newLink = newIntLink();
2245 case RESULT_TYPE_BIT:
2247 /* already an int */
2248 bitsForType (tree->etype) >= 16 ||
2249 /* bit to bit operation: don't promote, the code generators
2250 hopefully know everything about promotion rules */
2251 bitsForType (tree->etype) == 1)
2253 newLink = newIntLink();
2256 case RESULT_TYPE_CHAR:
2257 if (IS_CHAR (tree->etype) ||
2258 IS_FLOAT(tree->etype) ||
2259 IS_FIXED(tree->etype))
2261 newLink = newCharLink();
2263 case RESULT_TYPE_INT:
2265 if (getSize (tree->etype) > INTSIZE)
2267 /* warn ("Loosing significant digits"); */
2271 /* char: promote to int */
2273 getSize (tree->etype) >= INTSIZE)
2275 newLink = newIntLink();
2278 case RESULT_TYPE_IFX:
2279 case RESULT_TYPE_OTHER:
2281 /* return type is ifx, long, float: promote char to int */
2282 getSize (tree->etype) >= INTSIZE)
2284 newLink = newIntLink();
2290 tree->decorated = 0;
2291 tree = newNode (CAST, newAst_LINK (newLink), tree);
2292 tree->filename = tree->right->filename;
2293 tree->lineno = tree->right->lineno;
2294 /* keep unsigned type during cast to smaller type,
2295 but not when promoting from char to int */
2297 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2298 return decorateType (tree, resultType);
2301 /*-----------------------------------------------------------------*/
2302 /* resultTypePropagate - decides if resultType can be propagated */
2303 /*-----------------------------------------------------------------*/
2305 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2307 switch (tree->opval.op)
2324 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2325 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2326 return RESULT_TYPE_NONE;
2331 return RESULT_TYPE_NONE;
2335 return RESULT_TYPE_IFX;
2337 return RESULT_TYPE_NONE;
2341 /*-----------------------------------------------------------------*/
2342 /* getLeftResultType - gets type from left branch for propagation */
2343 /*-----------------------------------------------------------------*/
2345 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2347 switch (tree->opval.op)
2351 if (IS_PTR (LTYPE (tree)))
2352 return RESULT_TYPE_NONE;
2354 return getResultTypeFromType (LETYPE (tree));
2356 if (IS_PTR (currFunc->type->next))
2357 return RESULT_TYPE_NONE;
2359 return getResultTypeFromType (currFunc->type->next);
2361 if (!IS_ARRAY (LTYPE (tree)))
2363 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2364 return RESULT_TYPE_CHAR;
2371 /*------------------------------------------------------------------*/
2372 /* gatherImplicitVariables: assigns correct type information to */
2373 /* symbols and values created by replaceAstWithTemporary */
2374 /* and adds the symbols to the declarations list of the */
2375 /* innermost block that contains them */
2376 /*------------------------------------------------------------------*/
2378 gatherImplicitVariables (ast * tree, ast * block)
2383 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2385 /* keep track of containing scope */
2388 if (tree->type == EX_OP && tree->opval.op == '=' &&
2389 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2391 symbol *assignee = tree->left->opval.val->sym;
2393 /* special case for assignment to compiler-generated temporary variable:
2394 compute type of RHS, and set the symbol's type to match */
2395 if (assignee->type == NULL && assignee->infertype) {
2396 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2398 if (dtr != tree->right)
2401 assignee->type = copyLinkChain(TTYPE(dtr));
2402 assignee->etype = getSpec(assignee->type);
2403 SPEC_SCLS (assignee->etype) = S_AUTO;
2404 SPEC_OCLS (assignee->etype) = NULL;
2405 SPEC_EXTR (assignee->etype) = 0;
2406 SPEC_STAT (assignee->etype) = 0;
2407 SPEC_VOLATILE (assignee->etype) = 0;
2408 SPEC_ABSA (assignee->etype) = 0;
2410 wassertl(block != NULL, "implicit variable not contained in block");
2411 wassert(assignee->next == NULL);
2412 if (block != NULL) {
2413 symbol **decl = &(block->values.sym);
2416 wassert(*decl != assignee); /* should not already be in list */
2417 decl = &( (*decl)->next );
2424 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2425 tree->opval.val->type == NULL &&
2426 tree->opval.val->sym &&
2427 tree->opval.val->sym->infertype)
2429 /* fixup type of value for compiler-inferred temporary var */
2430 tree->opval.val->type = tree->opval.val->sym->type;
2431 tree->opval.val->etype = tree->opval.val->sym->etype;
2434 gatherImplicitVariables(tree->left, block);
2435 gatherImplicitVariables(tree->right, block);
2438 /*--------------------------------------------------------------------*/
2439 /* decorateType - compute type for this tree, also does type checking.*/
2440 /* This is done bottom up, since type has to flow upwards. */
2441 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2442 /* result is a char and the operand(s) are int's. */
2443 /* It also does constant folding, and parameter checking. */
2444 /*--------------------------------------------------------------------*/
2446 decorateType (ast * tree, RESULT_TYPE resultType)
2450 RESULT_TYPE resultTypeProp;
2455 /* if already has type then do nothing */
2456 if (tree->decorated)
2459 tree->decorated = 1;
2462 /* print the line */
2463 /* if not block & function */
2464 if (tree->type == EX_OP &&
2465 (tree->opval.op != FUNCTION &&
2466 tree->opval.op != BLOCK &&
2467 tree->opval.op != NULLOP))
2469 filename = tree->filename;
2470 lineno = tree->lineno;
2474 /* if any child is an error | this one is an error do nothing */
2475 if (tree->isError ||
2476 (tree->left && tree->left->isError) ||
2477 (tree->right && tree->right->isError))
2480 /*------------------------------------------------------------------*/
2481 /*----------------------------*/
2482 /* leaf has been reached */
2483 /*----------------------------*/
2484 filename = tree->filename;
2485 lineno = tree->lineno;
2486 /* if this is of type value */
2487 /* just get the type */
2488 if (tree->type == EX_VALUE)
2491 if (IS_LITERAL (tree->opval.val->etype))
2494 /* if this is a character array then declare it */
2495 if (IS_ARRAY (tree->opval.val->type))
2496 tree->opval.val = stringToSymbol (tree->opval.val);
2498 /* otherwise just copy the type information */
2499 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2503 if (tree->opval.val->sym)
2505 /* if the undefined flag is set then give error message */
2506 if (tree->opval.val->sym->undefined)
2508 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2510 TTYPE (tree) = TETYPE (tree) =
2511 tree->opval.val->type = tree->opval.val->sym->type =
2512 tree->opval.val->etype = tree->opval.val->sym->etype =
2513 copyLinkChain (INTTYPE);
2515 else if (tree->opval.val->sym->implicit)
2517 /* if implicit i.e. struct/union member then no type */
2518 TTYPE (tree) = TETYPE (tree) = NULL;
2522 /* copy the type from the value into the ast */
2523 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2525 /* and mark the symbol as referenced */
2526 tree->opval.val->sym->isref = 1;
2530 wassert(0); /* unreached: all values are literals or symbols */
2535 /* if type link for the case of cast */
2536 if (tree->type == EX_LINK)
2538 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2546 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2548 if (tree->left && tree->left->type == EX_OPERAND
2549 && (tree->left->opval.op == INC_OP
2550 || tree->left->opval.op == DEC_OP)
2551 && tree->left->left)
2553 tree->left->right = tree->left->left;
2554 tree->left->left = NULL;
2556 if (tree->right && tree->right->type == EX_OPERAND
2557 && (tree->right->opval.op == INC_OP
2558 || tree->right->opval.op == DEC_OP)
2559 && tree->right->left)
2561 tree->right->right = tree->right->left;
2562 tree->right->left = NULL;
2567 /* Before decorating the left branch we've to decide in dependence
2568 upon tree->opval.op, if resultType can be propagated */
2569 resultTypeProp = resultTypePropagate (tree, resultType);
2571 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2572 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2574 dtl = decorateType (tree->left, resultTypeProp);
2576 /* if an array node, we may need to swap branches */
2577 if (tree->opval.op == '[')
2579 /* determine which is the array & which the index */
2580 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2581 IS_INTEGRAL (LTYPE (tree)))
2583 ast *tempTree = tree->left;
2584 tree->left = tree->right;
2585 tree->right = tempTree;
2589 /* After decorating the left branch there's type information available
2590 in tree->left->?type. If the op is e.g. '=' we extract the type
2591 information from there and propagate it to the right branch. */
2592 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2594 switch (tree->opval.op)
2597 /* delay right side for '?' operator since conditional macro
2598 expansions might rely on this */
2602 /* decorate right side for CALL (parameter list) in processParms();
2603 there is resultType available */
2607 /* don't allocate string if it is a sizeof argument */
2609 dtr = decorateType (tree->right, resultTypeProp);
2613 dtr = decorateType (tree->right, resultTypeProp);
2617 /* this is to take care of situations
2618 when the tree gets rewritten */
2619 if (dtl != tree->left)
2621 if (dtr != tree->right)
2623 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2627 /* depending on type of operator do */
2629 switch (tree->opval.op)
2631 /*------------------------------------------------------------------*/
2632 /*----------------------------*/
2634 /*----------------------------*/
2637 /* first check if this is a array or a pointer */
2638 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2640 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2641 goto errorTreeReturn;
2644 /* check if the type of the idx */
2645 if (!IS_INTEGRAL (RTYPE (tree)))
2647 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2648 goto errorTreeReturn;
2651 /* if the left is an rvalue then error */
2654 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2655 goto errorTreeReturn;
2658 if (IS_LITERAL (RTYPE (tree)))
2660 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2661 int arraySize = DCL_ELEM (LTYPE (tree));
2662 if (arraySize && arrayIndex >= arraySize)
2664 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2669 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2670 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2673 /*------------------------------------------------------------------*/
2674 /*----------------------------*/
2676 /*----------------------------*/
2678 /* if this is not a structure */
2679 if (!IS_STRUCT (LTYPE (tree)))
2681 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2682 goto errorTreeReturn;
2684 TTYPE (tree) = structElemType (LTYPE (tree),
2685 (tree->right->type == EX_VALUE ?
2686 tree->right->opval.val : NULL));
2687 TETYPE (tree) = getSpec (TTYPE (tree));
2690 /*------------------------------------------------------------------*/
2691 /*----------------------------*/
2692 /* struct/union pointer */
2693 /*----------------------------*/
2695 /* if not pointer to a structure */
2696 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2698 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2699 goto errorTreeReturn;
2702 if (!IS_STRUCT (LTYPE (tree)->next))
2704 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2705 goto errorTreeReturn;
2708 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2709 (tree->right->type == EX_VALUE ?
2710 tree->right->opval.val : NULL));
2711 TETYPE (tree) = getSpec (TTYPE (tree));
2713 /* adjust the storage class */
2714 switch (DCL_TYPE(tree->left->ftype)) {
2716 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2719 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2722 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2725 SPEC_SCLS (TETYPE (tree)) = 0;
2728 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2731 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2734 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2737 SPEC_SCLS (TETYPE (tree)) = 0;
2744 /* This breaks with extern declarations, bitfields, and perhaps other */
2745 /* cases (gcse). Let's leave this optimization disabled for now and */
2746 /* ponder if there's a safe way to do this. -- EEP */
2748 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2749 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2751 /* If defined struct type at addr var
2752 then rewrite (&struct var)->member
2754 and define membertype at (addr+offsetof(struct var,member)) temp
2757 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2758 AST_SYMBOL(tree->right));
2760 sym = newSymbol(genSymName (0), 0);
2761 sym->type = TTYPE (tree);
2762 sym->etype = getSpec(sym->type);
2763 sym->lineDef = tree->lineno;
2766 SPEC_STAT (sym->etype) = 1;
2767 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2769 SPEC_ABSA(sym->etype) = 1;
2770 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2773 AST_VALUE (tree) = symbolVal(sym);
2776 tree->type = EX_VALUE;
2784 /*------------------------------------------------------------------*/
2785 /*----------------------------*/
2786 /* ++/-- operation */
2787 /*----------------------------*/
2791 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2792 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2793 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2794 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2803 /*------------------------------------------------------------------*/
2804 /*----------------------------*/
2806 /*----------------------------*/
2807 case '&': /* can be unary */
2808 /* if right is NULL then unary operation */
2809 if (tree->right) /* not an unary operation */
2812 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2814 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2815 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2816 printTypeChain (LTYPE (tree), stderr);
2817 fprintf (stderr, ",");
2818 printTypeChain (RTYPE (tree), stderr);
2819 fprintf (stderr, "\n");
2820 goto errorTreeReturn;
2823 /* if they are both literal */
2824 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2826 tree->type = EX_VALUE;
2827 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2828 valFromType (RETYPE (tree)), '&');
2830 tree->right = tree->left = NULL;
2831 TETYPE (tree) = tree->opval.val->etype;
2832 TTYPE (tree) = tree->opval.val->type;
2836 /* see if this is a GETHBIT operation if yes
2839 ast *otree = optimizeGetHbit (tree, resultType);
2842 return decorateType (otree, RESULT_TYPE_NONE);
2845 /* see if this is a GETABIT operation if yes
2848 ast *otree = optimizeGetAbit (tree, resultType);
2851 return decorateType (otree, RESULT_TYPE_NONE);
2854 /* see if this is a GETBYTE operation if yes
2857 ast *otree = optimizeGetByte (tree, resultType);
2860 return decorateType (otree, RESULT_TYPE_NONE);
2863 /* see if this is a GETWORD operation if yes
2866 ast *otree = optimizeGetWord (tree, resultType);
2869 return decorateType (otree, RESULT_TYPE_NONE);
2872 /* if left is a literal exchange left & right */
2873 if (IS_LITERAL (LTYPE (tree)))
2875 ast *tTree = tree->left;
2876 tree->left = tree->right;
2877 tree->right = tTree;
2880 /* if right is a literal and */
2881 /* we can find a 2nd literal in an and-tree then */
2882 /* rearrange the tree */
2883 if (IS_LITERAL (RTYPE (tree)))
2886 ast *litTree = searchLitOp (tree, &parent, "&");
2890 ast *tTree = litTree->left;
2891 litTree->left = tree->right;
2892 tree->right = tTree;
2893 /* both operands in litTree are literal now */
2894 decorateType (parent, resultType);
2898 LRVAL (tree) = RRVAL (tree) = 1;
2900 TTYPE (tree) = computeType (LTYPE (tree),
2904 TETYPE (tree) = getSpec (TTYPE (tree));
2909 /*------------------------------------------------------------------*/
2910 /*----------------------------*/
2912 /*----------------------------*/
2913 p = newLink (DECLARATOR);
2914 /* if bit field then error */
2915 if (IS_BITVAR (tree->left->etype))
2917 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2918 goto errorTreeReturn;
2921 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2923 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2924 goto errorTreeReturn;
2927 if (IS_FUNC (LTYPE (tree)))
2929 // this ought to be ignored
2930 return (tree->left);
2933 if (IS_LITERAL(LTYPE(tree)))
2935 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2936 goto errorTreeReturn;
2941 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2942 goto errorTreeReturn;
2945 DCL_TYPE (p) = POINTER;
2946 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2947 DCL_TYPE (p) = CPOINTER;
2948 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2949 DCL_TYPE (p) = FPOINTER;
2950 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2951 DCL_TYPE (p) = PPOINTER;
2952 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2953 DCL_TYPE (p) = IPOINTER;
2954 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2955 DCL_TYPE (p) = EEPPOINTER;
2956 else if (SPEC_OCLS(tree->left->etype))
2957 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2959 DCL_TYPE (p) = POINTER;
2961 if (IS_AST_SYM_VALUE (tree->left))
2963 AST_SYMBOL (tree->left)->addrtaken = 1;
2964 AST_SYMBOL (tree->left)->allocreq = 1;
2967 p->next = LTYPE (tree);
2969 TETYPE (tree) = getSpec (TTYPE (tree));
2974 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2975 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2977 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2978 AST_SYMBOL(tree->left->right));
2979 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2980 valueFromLit(element->offset));
2983 tree->type = EX_VALUE;
2984 tree->values.literalFromCast = 1;
2990 /*------------------------------------------------------------------*/
2991 /*----------------------------*/
2993 /*----------------------------*/
2995 /* if the rewrite succeeds then don't go any further */
2997 ast *wtree = optimizeRRCRLC (tree);
2999 return decorateType (wtree, RESULT_TYPE_NONE);
3001 wtree = optimizeSWAP (tree);
3003 return decorateType (wtree, RESULT_TYPE_NONE);
3006 /* if left is a literal exchange left & right */
3007 if (IS_LITERAL (LTYPE (tree)))
3009 ast *tTree = tree->left;
3010 tree->left = tree->right;
3011 tree->right = tTree;
3014 /* if right is a literal and */
3015 /* we can find a 2nd literal in an or-tree then */
3016 /* rearrange the tree */
3017 if (IS_LITERAL (RTYPE (tree)))
3020 ast *litTree = searchLitOp (tree, &parent, "|");
3024 ast *tTree = litTree->left;
3025 litTree->left = tree->right;
3026 tree->right = tTree;
3027 /* both operands in tTree are literal now */
3028 decorateType (parent, resultType);
3033 /*------------------------------------------------------------------*/
3034 /*----------------------------*/
3036 /*----------------------------*/
3038 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3040 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3041 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3042 printTypeChain (LTYPE (tree), stderr);
3043 fprintf (stderr, ",");
3044 printTypeChain (RTYPE (tree), stderr);
3045 fprintf (stderr, "\n");
3046 goto errorTreeReturn;
3049 /* if they are both literal then rewrite the tree */
3050 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3052 tree->type = EX_VALUE;
3053 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3054 valFromType (RETYPE (tree)),
3056 tree->right = tree->left = NULL;
3057 TETYPE (tree) = tree->opval.val->etype;
3058 TTYPE (tree) = tree->opval.val->type;
3062 /* if left is a literal exchange left & right */
3063 if (IS_LITERAL (LTYPE (tree)))
3065 ast *tTree = tree->left;
3066 tree->left = tree->right;
3067 tree->right = tTree;
3070 /* if right is a literal and */
3071 /* we can find a 2nd literal in a xor-tree then */
3072 /* rearrange the tree */
3073 if (IS_LITERAL (RTYPE (tree)) &&
3074 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3077 ast *litTree = searchLitOp (tree, &parent, "^");
3081 ast *tTree = litTree->left;
3082 litTree->left = tree->right;
3083 tree->right = tTree;
3084 /* both operands in litTree are literal now */
3085 decorateType (parent, resultType);
3089 LRVAL (tree) = RRVAL (tree) = 1;
3091 TTYPE (tree) = computeType (LTYPE (tree),
3095 TETYPE (tree) = getSpec (TTYPE (tree));
3099 /*------------------------------------------------------------------*/
3100 /*----------------------------*/
3102 /*----------------------------*/
3104 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3106 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3107 goto errorTreeReturn;
3109 /* if they are both literal then */
3110 /* rewrite the tree */
3111 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3113 tree->type = EX_VALUE;
3114 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3115 valFromType (RETYPE (tree)));
3116 tree->right = tree->left = NULL;
3117 TETYPE (tree) = getSpec (TTYPE (tree) =
3118 tree->opval.val->type);
3122 LRVAL (tree) = RRVAL (tree) = 1;
3124 TETYPE (tree) = getSpec (TTYPE (tree) =
3125 computeType (LTYPE (tree),
3130 /* if right is a literal and */
3131 /* left is also a division by a literal then */
3132 /* rearrange the tree */
3133 if (IS_LITERAL (RTYPE (tree))
3134 /* avoid infinite loop */
3135 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3138 ast *litTree = searchLitOp (tree, &parent, "/");
3141 if (IS_LITERAL (RTYPE (litTree)))
3145 litTree->right = newNode ('*',
3147 copyAst (tree->right));
3148 litTree->right->filename = tree->filename;
3149 litTree->right->lineno = tree->lineno;
3151 tree->right->opval.val = constCharVal (1);
3152 decorateType (parent, resultType);
3156 /* litTree->left is literal: no gcse possible.
3157 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3158 this would cause an infinit loop. */
3159 parent->decorated = 1;
3160 decorateType (litTree, resultType);
3167 /*------------------------------------------------------------------*/
3168 /*----------------------------*/
3170 /*----------------------------*/
3172 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3174 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3175 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3176 printTypeChain (LTYPE (tree), stderr);
3177 fprintf (stderr, ",");
3178 printTypeChain (RTYPE (tree), stderr);
3179 fprintf (stderr, "\n");
3180 goto errorTreeReturn;
3182 /* if they are both literal then */
3183 /* rewrite the tree */
3184 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3186 tree->type = EX_VALUE;
3187 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3188 valFromType (RETYPE (tree)));
3189 tree->right = tree->left = NULL;
3190 TETYPE (tree) = getSpec (TTYPE (tree) =
3191 tree->opval.val->type);
3194 LRVAL (tree) = RRVAL (tree) = 1;
3195 TETYPE (tree) = getSpec (TTYPE (tree) =
3196 computeType (LTYPE (tree),
3202 /*------------------------------------------------------------------*/
3203 /*----------------------------*/
3204 /* address dereference */
3205 /*----------------------------*/
3206 case '*': /* can be unary : if right is null then unary operation */
3209 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3211 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3212 goto errorTreeReturn;
3217 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3218 goto errorTreeReturn;
3220 if (IS_ADDRESS_OF_OP(tree->left))
3222 /* replace *&obj with obj */
3223 return tree->left->left;
3225 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3226 TETYPE (tree) = getSpec (TTYPE (tree));
3227 /* adjust the storage class */
3228 switch (DCL_TYPE(tree->left->ftype)) {
3230 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3233 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3236 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3239 SPEC_SCLS (TETYPE (tree)) = 0;
3242 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3245 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3248 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3251 SPEC_SCLS (TETYPE (tree)) = 0;
3260 /*------------------------------------------------------------------*/
3261 /*----------------------------*/
3262 /* multiplication */
3263 /*----------------------------*/
3264 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3266 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3267 goto errorTreeReturn;
3270 /* if they are both literal then */
3271 /* rewrite the tree */
3272 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3274 tree->type = EX_VALUE;
3275 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3276 valFromType (RETYPE (tree)));
3277 tree->right = tree->left = NULL;
3278 TETYPE (tree) = getSpec (TTYPE (tree) =
3279 tree->opval.val->type);
3283 /* if left is a literal exchange left & right */
3284 if (IS_LITERAL (LTYPE (tree)))
3286 ast *tTree = tree->left;
3287 tree->left = tree->right;
3288 tree->right = tTree;
3291 /* if right is a literal and */
3292 /* we can find a 2nd literal in a mul-tree then */
3293 /* rearrange the tree */
3294 if (IS_LITERAL (RTYPE (tree)))
3297 ast *litTree = searchLitOp (tree, &parent, "*");
3301 ast *tTree = litTree->left;
3302 litTree->left = tree->right;
3303 tree->right = tTree;
3304 /* both operands in litTree are literal now */
3305 decorateType (parent, resultType);
3309 LRVAL (tree) = RRVAL (tree) = 1;
3310 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3311 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3312 TETYPE (tree) = getSpec (TTYPE (tree) =
3313 computeType (LTYPE (tree),
3320 /*------------------------------------------------------------------*/
3321 /*----------------------------*/
3322 /* unary '+' operator */
3323 /*----------------------------*/
3328 if (!IS_ARITHMETIC (LTYPE (tree)))
3330 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3331 goto errorTreeReturn;
3334 /* if left is a literal then do it */
3335 if (IS_LITERAL (LTYPE (tree)))
3337 tree->type = EX_VALUE;
3338 tree->opval.val = valFromType (LETYPE (tree));
3340 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3344 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3348 /*------------------------------------------------------------------*/
3349 /*----------------------------*/
3351 /*----------------------------*/
3353 /* this is not a unary operation */
3354 /* if both pointers then problem */
3355 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3356 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3358 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3359 goto errorTreeReturn;
3362 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3363 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3365 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3366 goto errorTreeReturn;
3369 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3370 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3372 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3373 goto errorTreeReturn;
3375 /* if they are both literal then */
3376 /* rewrite the tree */
3377 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3379 tree->type = EX_VALUE;
3380 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3381 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3382 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3383 valFromType (RETYPE (tree)));
3384 tree->right = tree->left = NULL;
3385 TETYPE (tree) = getSpec (TTYPE (tree) =
3386 tree->opval.val->type);
3390 /* if the right is a pointer or left is a literal
3391 xchange left & right */
3392 if (IS_ARRAY (RTYPE (tree)) ||
3393 IS_PTR (RTYPE (tree)) ||
3394 IS_LITERAL (LTYPE (tree)))
3396 ast *tTree = tree->left;
3397 tree->left = tree->right;
3398 tree->right = tTree;
3401 /* if right is a literal and */
3402 /* left is also an addition/subtraction with a literal then */
3403 /* rearrange the tree */
3404 if (IS_LITERAL (RTYPE (tree)))
3406 ast *litTree, *parent;
3407 litTree = searchLitOp (tree, &parent, "+-");
3410 if (litTree->opval.op == '+')
3414 ast *tTree = litTree->left;
3415 litTree->left = tree->right;
3416 tree->right = tree->left;
3419 else if (litTree->opval.op == '-')
3421 if (IS_LITERAL (RTYPE (litTree)))
3425 ast *tTree = litTree->left;
3426 litTree->left = tree->right;
3427 tree->right = tTree;
3433 ast *tTree = litTree->right;
3434 litTree->right = tree->right;
3435 tree->right = tTree;
3436 litTree->opval.op = '+';
3437 tree->opval.op = '-';
3440 decorateType (parent, resultType);
3444 LRVAL (tree) = RRVAL (tree) = 1;
3445 /* if the left is a pointer */
3446 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3447 TETYPE (tree) = getSpec (TTYPE (tree) =
3451 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3452 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3453 TETYPE (tree) = getSpec (TTYPE (tree) =
3454 computeType (LTYPE (tree),
3462 /*------------------------------------------------------------------*/
3463 /*----------------------------*/
3465 /*----------------------------*/
3466 case '-': /* can be unary */
3467 /* if right is null then unary */
3471 if (!IS_ARITHMETIC (LTYPE (tree)))
3473 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3474 goto errorTreeReturn;
3477 /* if left is a literal then do it */
3478 if (IS_LITERAL (LTYPE (tree)))
3480 tree->type = EX_VALUE;
3481 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3483 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3486 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3487 TETYPE (tree) = getSpec (TTYPE (tree) =
3488 computeType (LTYPE (tree),
3496 /*------------------------------------------------------------------*/
3497 /*----------------------------*/
3499 /*----------------------------*/
3501 if (!(IS_PTR (LTYPE (tree)) ||
3502 IS_ARRAY (LTYPE (tree)) ||
3503 IS_ARITHMETIC (LTYPE (tree))))
3505 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3506 goto errorTreeReturn;
3509 if (!(IS_PTR (RTYPE (tree)) ||
3510 IS_ARRAY (RTYPE (tree)) ||
3511 IS_ARITHMETIC (RTYPE (tree))))
3513 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3514 goto errorTreeReturn;
3517 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3518 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3519 IS_INTEGRAL (RTYPE (tree))))
3521 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3522 goto errorTreeReturn;
3525 /* if they are both literal then */
3526 /* rewrite the tree */
3527 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3529 tree->type = EX_VALUE;
3530 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3531 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3532 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3533 valFromType (RETYPE (tree)));
3534 tree->right = tree->left = NULL;
3535 TETYPE (tree) = getSpec (TTYPE (tree) =
3536 tree->opval.val->type);
3540 /* if the left & right are equal then zero */
3541 if (isAstEqual (tree->left, tree->right))
3543 tree->type = EX_VALUE;
3544 tree->left = tree->right = NULL;
3545 tree->opval.val = constCharVal (0);
3546 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3550 /* if both of them are pointers or arrays then */
3551 /* the result is going to be an integer */
3552 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3553 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3554 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3556 /* if only the left is a pointer */
3557 /* then result is a pointer */
3558 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3559 TETYPE (tree) = getSpec (TTYPE (tree) =
3563 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3564 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3566 TETYPE (tree) = getSpec (TTYPE (tree) =
3567 computeType (LTYPE (tree),
3573 LRVAL (tree) = RRVAL (tree) = 1;
3575 /* if right is a literal and */
3576 /* left is also an addition/subtraction with a literal then */
3577 /* rearrange the tree */
3578 if (IS_LITERAL (RTYPE (tree))
3579 /* avoid infinite loop */
3580 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3582 ast *litTree, *litParent;
3583 litTree = searchLitOp (tree, &litParent, "+-");
3586 if (litTree->opval.op == '+')
3590 ast *tTree = litTree->left;
3591 litTree->left = litTree->right;
3592 litTree->right = tree->right;
3593 tree->right = tTree;
3594 tree->opval.op = '+';
3595 litTree->opval.op = '-';
3597 else if (litTree->opval.op == '-')
3599 if (IS_LITERAL (RTYPE (litTree)))
3603 ast *tTree = litTree->left;
3604 litTree->left = tree->right;
3605 tree->right = litParent->left;
3606 litParent->left = tTree;
3607 litTree->opval.op = '+';
3609 tree->decorated = 0;
3610 decorateType (tree, resultType);
3616 ast *tTree = litTree->right;
3617 litTree->right = tree->right;
3618 tree->right = tTree;
3621 decorateType (litParent, resultType);
3626 /*------------------------------------------------------------------*/
3627 /*----------------------------*/
3629 /*----------------------------*/
3631 /* can be only integral type */
3632 if (!IS_INTEGRAL (LTYPE (tree)))
3634 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3635 goto errorTreeReturn;
3638 /* if left is a literal then do it */
3639 if (IS_LITERAL (LTYPE (tree)))
3641 tree->type = EX_VALUE;
3642 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3644 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3645 return addCast (tree, resultTypeProp, TRUE);
3648 if (resultType == RESULT_TYPE_BIT &&
3649 IS_UNSIGNED (tree->left->etype) &&
3650 getSize (tree->left->etype) < INTSIZE)
3652 /* promotion rules are responsible for this strange result:
3653 bit -> int -> ~int -> bit
3654 uchar -> int -> ~int -> bit
3656 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3658 /* optimize bit-result, even if we optimize a buggy source */
3659 tree->type = EX_VALUE;
3660 tree->opval.val = constCharVal (1);
3663 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3665 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3668 /*------------------------------------------------------------------*/
3669 /*----------------------------*/
3671 /*----------------------------*/
3673 /* can be pointer */
3674 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3675 !IS_PTR (LTYPE (tree)) &&
3676 !IS_ARRAY (LTYPE (tree)))
3678 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3679 goto errorTreeReturn;
3682 /* if left is another '!' */
3683 if (IS_AST_NOT_OPER (tree->left))
3685 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3687 /* replace double '!!X' by 'X' */
3688 return tree->left->left;
3690 /* remove double '!!X' by 'X ? 1 : 0' */
3691 tree->opval.op = '?';
3692 tree->left = tree->left->left;
3693 tree->right = newNode (':',
3694 newAst_VALUE (constCharVal (1)),
3695 newAst_VALUE (constCharVal (0)));
3696 tree->right->filename = tree->filename;
3697 tree->right->lineno = tree->lineno;
3698 tree->decorated = 0;
3699 return decorateType (tree, resultType);
3702 /* if left is a literal then do it */
3703 if (IS_LITERAL (LTYPE (tree)))
3705 tree->type = EX_VALUE;
3706 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3708 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3712 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3715 /*------------------------------------------------------------------*/
3716 /*----------------------------*/
3718 /*----------------------------*/
3722 TTYPE (tree) = LTYPE (tree);
3723 TETYPE (tree) = LETYPE (tree);
3728 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3732 TTYPE (tree) = TETYPE (tree) = newCharLink();
3736 TTYPE (tree) = TETYPE (tree) = newIntLink();
3741 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3743 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3744 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3745 printTypeChain (LTYPE (tree), stderr);
3746 fprintf (stderr, ",");
3747 printTypeChain (RTYPE (tree), stderr);
3748 fprintf (stderr, "\n");
3749 goto errorTreeReturn;
3752 /* make smaller type only if it's a LEFT_OP */
3753 if (tree->opval.op == LEFT_OP)
3754 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3756 /* if they are both literal then */
3757 /* rewrite the tree */
3758 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3760 tree->type = EX_VALUE;
3761 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3762 valFromType (RETYPE (tree)),
3763 (tree->opval.op == LEFT_OP ? 1 : 0));
3764 tree->right = tree->left = NULL;
3765 TETYPE (tree) = getSpec (TTYPE (tree) =
3766 tree->opval.val->type);
3770 /* see if this is a GETBYTE operation if yes
3773 ast *otree = optimizeGetByte (tree, resultType);
3776 return decorateType (otree, RESULT_TYPE_NONE);
3779 /* see if this is a GETWORD operation if yes
3782 ast *otree = optimizeGetWord (tree, resultType);
3785 return decorateType (otree, RESULT_TYPE_NONE);
3788 LRVAL (tree) = RRVAL (tree) = 1;
3789 if (tree->opval.op == LEFT_OP)
3791 TETYPE (tree) = getSpec (TTYPE (tree) =
3792 computeType (LTYPE (tree),
3799 /* no promotion necessary */
3800 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3801 if (IS_LITERAL (TTYPE (tree)))
3802 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3805 /* if only the right side is a literal & we are
3806 shifting more than size of the left operand then zero */
3807 if (IS_LITERAL (RTYPE (tree)) &&
3808 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3809 (getSize (TETYPE (tree)) * 8))
3811 if (tree->opval.op==LEFT_OP ||
3812 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3814 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3815 (tree->opval.op == LEFT_OP ? "left" : "right"));
3816 tree->type = EX_VALUE;
3817 tree->left = tree->right = NULL;
3818 tree->opval.val = constCharVal (0);
3819 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3826 /*------------------------------------------------------------------*/
3827 /*----------------------------*/
3829 /*----------------------------*/
3830 case CAST: /* change the type */
3831 /* cannot cast to an aggregate type */
3832 if (IS_AGGREGATE (LTYPE (tree)))
3834 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3835 goto errorTreeReturn;
3838 /* make sure the type is complete and sane */
3839 changePointer(LTYPE(tree));
3840 checkTypeSanity(LETYPE(tree), "(cast)");
3843 /* if 'from' and 'to' are the same remove the superfluous cast,
3844 * this helps other optimizations */
3845 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3847 /* mark that the explicit cast has been removed,
3848 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3849 tree->right->values.removedCast = 1;
3853 /* If code memory is read only, then pointers to code memory */
3854 /* implicitly point to constants -- make this explicit */
3856 sym_link *t = LTYPE(tree);
3857 while (t && t->next)
3859 if (IS_CODEPTR(t) && port->mem.code_ro)
3861 if (IS_SPEC(t->next))
3862 SPEC_CONST (t->next) = 1;
3864 DCL_PTR_CONST (t->next) = 1;
3871 /* if the right is a literal replace the tree */
3872 if (IS_LITERAL (RETYPE (tree))) {
3873 if (!IS_PTR (LTYPE (tree))) {
3874 tree->type = EX_VALUE;
3876 valCastLiteral (LTYPE (tree),
3877 floatFromVal (valFromType (RETYPE (tree))));
3880 TTYPE (tree) = tree->opval.val->type;
3881 tree->values.literalFromCast = 1;
3882 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3883 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3884 sym_link *rest = LTYPE(tree)->next;
3885 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3886 TTYPE(tree) = newLink(DECLARATOR);
3887 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3888 TTYPE(tree)->next = rest;
3889 tree->left->opval.lnk = TTYPE(tree);
3892 TTYPE (tree) = LTYPE (tree);
3896 TTYPE (tree) = LTYPE (tree);
3900 #if 0 // this is already checked, now this could be explicit
3901 /* if pointer to struct then check names */
3902 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3903 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3904 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3906 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3907 SPEC_STRUCT(LETYPE(tree))->tag);
3910 if (IS_ADDRESS_OF_OP(tree->right)
3911 && IS_AST_SYM_VALUE (tree->right->left)
3912 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3914 symbol * sym = AST_SYMBOL (tree->right->left);
3915 unsigned int gptype = 0;
3916 unsigned int addr = SPEC_ADDR (sym->etype);
3918 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3919 || TARGET_IS_PIC16) )
3921 switch (SPEC_SCLS (sym->etype))
3924 gptype = GPTYPE_CODE;
3927 gptype = GPTYPE_FAR;
3931 gptype = GPTYPE_NEAR;
3934 gptype = GPTYPE_XSTACK;
3939 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3940 gptype = GPTYPE_NEAR;
3942 addr |= gptype << (8*(GPTRSIZE - 1));
3945 tree->type = EX_VALUE;
3947 valCastLiteral (LTYPE (tree), addr);
3948 TTYPE (tree) = tree->opval.val->type;
3949 TETYPE (tree) = getSpec (TTYPE (tree));
3952 tree->values.literalFromCast = 1;
3956 /* handle offsetof macro: */
3957 /* #define offsetof(TYPE, MEMBER) \ */
3958 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3959 if (IS_ADDRESS_OF_OP(tree->right)
3960 && IS_AST_OP (tree->right->left)
3961 && tree->right->left->opval.op == PTR_OP
3962 && IS_AST_OP (tree->right->left->left)
3963 && tree->right->left->left->opval.op == CAST
3964 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3966 symbol *element = getStructElement (
3967 SPEC_STRUCT (LETYPE(tree->right->left)),
3968 AST_SYMBOL(tree->right->left->right)
3972 tree->type = EX_VALUE;
3973 tree->opval.val = valCastLiteral (
3976 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3979 TTYPE (tree) = tree->opval.val->type;
3980 TETYPE (tree) = getSpec (TTYPE (tree));
3987 /* if the right is a literal replace the tree */
3988 if (IS_LITERAL (RETYPE (tree))) {
3990 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3991 /* rewrite (type *)litaddr
3993 and define type at litaddr temp
3994 (but only if type's storage class is not generic)
3996 ast *newTree = newNode ('&', NULL, NULL);
3999 TTYPE (newTree) = LTYPE (tree);
4000 TETYPE (newTree) = getSpec(LTYPE (tree));
4002 /* define a global symbol at the casted address*/
4003 sym = newSymbol(genSymName (0), 0);
4004 sym->type = LTYPE (tree)->next;
4006 sym->type = newLink (V_VOID);
4007 sym->etype = getSpec(sym->type);
4008 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4009 sym->lineDef = tree->lineno;
4012 SPEC_STAT (sym->etype) = 1;
4013 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4014 SPEC_ABSA(sym->etype) = 1;
4015 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4018 newTree->left = newAst_VALUE(symbolVal(sym));
4019 newTree->left->filename = tree->filename;
4020 newTree->left->lineno = tree->lineno;
4021 LTYPE (newTree) = sym->type;
4022 LETYPE (newTree) = sym->etype;
4023 LLVAL (newTree) = 1;
4024 LRVAL (newTree) = 0;
4025 TLVAL (newTree) = 1;
4029 if (!IS_PTR (LTYPE (tree))) {
4030 tree->type = EX_VALUE;
4032 valCastLiteral (LTYPE (tree),
4033 floatFromVal (valFromType (RTYPE (tree))));
4034 TTYPE (tree) = tree->opval.val->type;
4037 tree->values.literalFromCast = 1;
4038 TETYPE (tree) = getSpec (TTYPE (tree));
4042 TTYPE (tree) = LTYPE (tree);
4046 TETYPE (tree) = getSpec (TTYPE (tree));
4050 /*------------------------------------------------------------------*/
4051 /*----------------------------*/
4052 /* logical &&, || */
4053 /*----------------------------*/
4056 /* each must be arithmetic type or be a pointer */
4057 if (!IS_PTR (LTYPE (tree)) &&
4058 !IS_ARRAY (LTYPE (tree)) &&
4059 !IS_INTEGRAL (LTYPE (tree)))
4061 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4062 goto errorTreeReturn;
4065 if (!IS_PTR (RTYPE (tree)) &&
4066 !IS_ARRAY (RTYPE (tree)) &&
4067 !IS_INTEGRAL (RTYPE (tree)))
4069 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4070 goto errorTreeReturn;
4072 /* if they are both literal then */
4073 /* rewrite the tree */
4074 if (IS_LITERAL (RTYPE (tree)) &&
4075 IS_LITERAL (LTYPE (tree)))
4077 tree->type = EX_VALUE;
4078 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4079 valFromType (RTYPE (tree)),
4081 tree->right = tree->left = NULL;
4082 TETYPE (tree) = getSpec (TTYPE (tree) =
4083 tree->opval.val->type);
4086 LRVAL (tree) = RRVAL (tree) = 1;
4087 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4090 /*------------------------------------------------------------------*/
4091 /*----------------------------*/
4092 /* comparison operators */
4093 /*----------------------------*/
4101 ast *lt = optimizeCompare (tree);
4107 /* if they are pointers they must be castable */
4108 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4110 if (tree->opval.op==EQ_OP &&
4111 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4112 // we cannot cast a gptr to a !gptr: switch the leaves
4113 struct ast *s=tree->left;
4114 tree->left=tree->right;
4117 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4119 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4120 fprintf (stderr, "comparing type ");
4121 printTypeChain (LTYPE (tree), stderr);
4122 fprintf (stderr, "to type ");
4123 printTypeChain (RTYPE (tree), stderr);
4124 fprintf (stderr, "\n");
4125 goto errorTreeReturn;
4128 /* else they should be promotable to one another */
4131 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4132 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4134 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4136 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4137 fprintf (stderr, "comparing type ");
4138 printTypeChain (LTYPE (tree), stderr);
4139 fprintf (stderr, "to type ");
4140 printTypeChain (RTYPE (tree), stderr);
4141 fprintf (stderr, "\n");
4142 goto errorTreeReturn;
4147 CCR_RESULT ccr_result = CCR_OK;
4149 /* if left is integral and right is literal
4150 then check constant range */
4151 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4152 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4153 tree->opval.op, FALSE);
4154 if (ccr_result == CCR_OK &&
4155 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4156 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4157 tree->opval.op, TRUE);
4160 case CCR_ALWAYS_TRUE:
4161 case CCR_ALWAYS_FALSE:
4162 if (!options.lessPedantic)
4163 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4164 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4165 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4172 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4173 if (tree->opval.op == '>' &&
4174 SPEC_USIGN(LETYPE(tree)) &&
4175 IS_LITERAL(RTYPE(tree)) &&
4176 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4178 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4180 /* the parent is an ifx: */
4181 /* if (unsigned value) */
4185 /* (unsigned value) ? 1 : 0 */
4186 tree->opval.op = '?';
4187 tree->right = newNode (':',
4188 newAst_VALUE (constCharVal (1)),
4189 tree->right); /* val 0 */
4190 tree->right->filename = tree->filename;
4191 tree->right->lineno = tree->lineno;
4192 tree->right->left->filename = tree->filename;
4193 tree->right->left->lineno = tree->lineno;
4194 tree->decorated = 0;
4195 return decorateType (tree, resultType);
4198 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4199 if (IS_LITERAL(RTYPE(tree)) &&
4200 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4201 tree->opval.op == EQ_OP &&
4202 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4204 tree->opval.op = '!';
4206 tree->decorated = 0;
4207 return decorateType (tree, resultType);
4210 /* if they are both literal then */
4211 /* rewrite the tree */
4212 if (IS_LITERAL (RTYPE (tree)) &&
4213 IS_LITERAL (LTYPE (tree)))
4215 tree->type = EX_VALUE;
4216 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4217 valFromType (RETYPE (tree)),
4219 tree->right = tree->left = NULL;
4220 TETYPE (tree) = getSpec (TTYPE (tree) =
4221 tree->opval.val->type);
4225 /* if one is 'signed char ' and the other one is 'unsigned char' */
4226 /* it's necessary to promote to int */
4227 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4228 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4230 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4231 if it's possible to use a 'signed char' */
4233 /* is left a 'unsigned char'? */
4234 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4235 /* the value range of a 'unsigned char' is 0...255;
4236 if the actual value is < 128 it can be changed to signed */
4237 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4239 /* now we've got 2 'signed char'! */
4240 SPEC_USIGN (RETYPE (tree)) = 0;
4242 /* same test for the left operand: */
4243 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4244 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4246 SPEC_USIGN (LETYPE (tree)) = 0;
4250 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4251 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4252 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4256 LRVAL (tree) = RRVAL (tree) = 1;
4257 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4259 /* condition transformations */
4261 unsigned transformedOp = 0;
4263 switch (tree->opval.op)
4265 case '<': /* transform (a < b) to !(a >= b) */
4267 transformedOp = GE_OP;
4269 case '>': /* transform (a > b) to !(a <= b) */
4271 transformedOp = LE_OP;
4273 case LE_OP: /* transform (a <= b) to !(a > b) */
4275 transformedOp = '>';
4277 case GE_OP: /* transform (a >= b) to !(a < b) */
4279 transformedOp = '<';
4281 case NE_OP: /* transform (a != b) to !(a == b) */
4283 transformedOp = EQ_OP;
4285 case EQ_OP: /* transform (a == b) to !(a != b) */
4287 transformedOp = NE_OP;
4294 tree->opval.op = transformedOp;
4295 tree->decorated = 0;
4296 tree = newNode ('!', tree, NULL);
4297 tree->filename = tree->left->filename;
4298 tree->lineno = tree->left->lineno;
4299 return decorateType (tree, resultType);
4305 /*------------------------------------------------------------------*/
4306 /*----------------------------*/
4308 /*----------------------------*/
4309 case SIZEOF: /* evaluate wihout code generation */
4310 /* change the type to a integer */
4312 int size = getSize (tree->right->ftype);
4314 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4315 if (!size && !IS_VOID(tree->right->ftype))
4316 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4318 tree->type = EX_VALUE;
4319 tree->opval.val = constVal (buffer);
4320 tree->right = tree->left = NULL;
4321 TETYPE (tree) = getSpec (TTYPE (tree) =
4322 tree->opval.val->type);
4326 /*------------------------------------------------------------------*/
4327 /*----------------------------*/
4329 /*----------------------------*/
4331 /* return typeof enum value */
4332 tree->type = EX_VALUE;
4335 if (IS_SPEC(tree->right->ftype)) {
4336 switch (SPEC_NOUN(tree->right->ftype)) {
4338 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4339 else typeofv = TYPEOF_INT;
4342 typeofv = TYPEOF_FLOAT;
4345 typeofv = TYPEOF_FIXED16X16;
4348 typeofv = TYPEOF_CHAR;
4351 typeofv = TYPEOF_VOID;
4354 typeofv = TYPEOF_STRUCT;
4357 typeofv = TYPEOF_BITFIELD;
4360 typeofv = TYPEOF_BIT;
4363 typeofv = TYPEOF_SBIT;
4369 switch (DCL_TYPE(tree->right->ftype)) {
4371 typeofv = TYPEOF_POINTER;
4374 typeofv = TYPEOF_FPOINTER;
4377 typeofv = TYPEOF_CPOINTER;
4380 typeofv = TYPEOF_GPOINTER;
4383 typeofv = TYPEOF_PPOINTER;
4386 typeofv = TYPEOF_IPOINTER;
4389 typeofv = TYPEOF_ARRAY;
4392 typeofv = TYPEOF_FUNCTION;
4398 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4399 tree->opval.val = constVal (buffer);
4400 tree->right = tree->left = NULL;
4401 TETYPE (tree) = getSpec (TTYPE (tree) =
4402 tree->opval.val->type);
4405 /*------------------------------------------------------------------*/
4406 /*----------------------------*/
4407 /* conditional operator '?' */
4408 /*----------------------------*/
4410 /* the type is value of the colon operator (on the right) */
4411 assert (IS_COLON_OP (tree->right));
4413 /* If already known then replace the tree : optimizer will do it
4414 but faster to do it here. If done before decorating tree->right
4415 this can save generating unused const strings. */
4416 if (IS_LITERAL (LTYPE (tree)))
4418 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4419 return decorateType (tree->right->left, resultTypeProp);
4421 return decorateType (tree->right->right, resultTypeProp);
4424 tree->right = decorateType (tree->right, resultTypeProp);
4426 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4427 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4429 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4430 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4432 if ((valTrue != 0) && (valFalse == 0))
4434 /* assign cond to result */
4435 tree->left->decorated = 0;
4436 return decorateType (tree->left, resultTypeProp);
4438 else if ((valTrue == 0) && (valFalse != 0))
4440 /* assign !cond to result */
4441 tree->opval.op = '!';
4442 tree->decorated = 0;
4444 return decorateType (tree, resultTypeProp);
4448 /* they have the same boolean value, make them equal */
4449 tree->right->left = tree->right->right;
4453 /* if they are equal then replace the tree */
4454 if (isAstEqual (tree->right->left, tree->right->right))
4456 return tree->right->left;
4459 TTYPE (tree) = RTYPE (tree);
4460 TETYPE (tree) = getSpec (TTYPE (tree));
4464 /* if they don't match we have a problem */
4465 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4466 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4468 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4469 goto errorTreeReturn;
4472 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4473 resultType, tree->opval.op);
4474 TETYPE (tree) = getSpec (TTYPE (tree));
4478 #if 0 // assignment operators are converted by the parser
4479 /*------------------------------------------------------------------*/
4480 /*----------------------------*/
4481 /* assignment operators */
4482 /*----------------------------*/
4485 /* for these it must be both must be integral */
4486 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4487 !IS_ARITHMETIC (RTYPE (tree)))
4489 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4490 goto errorTreeReturn;
4493 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4495 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4496 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4500 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4501 goto errorTreeReturn;
4512 /* for these it must be both must be integral */
4513 if (!IS_INTEGRAL (LTYPE (tree)) ||
4514 !IS_INTEGRAL (RTYPE (tree)))
4516 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4517 goto errorTreeReturn;
4520 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4522 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4523 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4527 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4528 goto errorTreeReturn;
4534 /*------------------------------------------------------------------*/
4535 /*----------------------------*/
4537 /*----------------------------*/
4539 if (!(IS_PTR (LTYPE (tree)) ||
4540 IS_ARITHMETIC (LTYPE (tree))))
4542 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4543 goto errorTreeReturn;
4546 if (!(IS_PTR (RTYPE (tree)) ||
4547 IS_ARITHMETIC (RTYPE (tree))))
4549 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4550 goto errorTreeReturn;
4553 TETYPE (tree) = getSpec (TTYPE (tree) =
4554 computeType (LTYPE (tree),
4559 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4560 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4564 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4565 goto errorTreeReturn;
4571 /*------------------------------------------------------------------*/
4572 /*----------------------------*/
4574 /*----------------------------*/
4576 /* this is not a unary operation */
4577 /* if both pointers then problem */
4578 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4580 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4581 goto errorTreeReturn;
4584 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4586 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4587 goto errorTreeReturn;
4590 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4592 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4593 goto errorTreeReturn;
4596 TETYPE (tree) = getSpec (TTYPE (tree) =
4597 computeType (LTYPE (tree),
4602 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4603 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4607 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4608 goto errorTreeReturn;
4611 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4612 tree->opval.op = '=';
4617 /*------------------------------------------------------------------*/
4618 /*----------------------------*/
4619 /* straight assignemnt */
4620 /*----------------------------*/
4622 /* cannot be an aggregate */
4623 if (IS_AGGREGATE (LTYPE (tree)))
4625 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4626 goto errorTreeReturn;
4629 /* they should either match or be castable */
4630 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4632 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4633 printFromToType(RTYPE(tree),LTYPE(tree));
4636 /* if the left side of the tree is of type void
4637 then report error */
4638 if (IS_VOID (LTYPE (tree)))
4640 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4641 printFromToType(RTYPE(tree), LTYPE(tree));
4644 TETYPE (tree) = getSpec (TTYPE (tree) =
4648 if (!tree->initMode ) {
4649 if (IS_CONSTANT(LTYPE(tree)))
4650 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4654 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4655 goto errorTreeReturn;
4660 /*------------------------------------------------------------------*/
4661 /*----------------------------*/
4662 /* comma operator */
4663 /*----------------------------*/
4665 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4668 /*------------------------------------------------------------------*/
4669 /*----------------------------*/
4671 /*----------------------------*/
4674 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4675 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4677 if (tree->left->opval.op == '*' && !tree->left->right)
4678 tree->left = tree->left->left;
4681 /* require a function or pointer to function */
4682 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4684 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4685 goto errorTreeReturn;
4688 /* if there are parms, make sure that
4689 parms are decorate / process / reverse only once */
4691 !tree->right->decorated)
4696 if (IS_FUNCPTR (LTYPE (tree)))
4698 functype = LTYPE (tree)->next;
4699 processFuncPtrArgs (functype);
4702 functype = LTYPE (tree);
4704 if (processParms (tree->left, FUNC_ARGS(functype),
4705 &tree->right, &parmNumber, TRUE))
4707 goto errorTreeReturn;
4710 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4711 !IFFUNC_ISBUILTIN(functype))
4713 reverseParms (tree->right);
4716 TTYPE (tree) = functype->next;
4717 TETYPE (tree) = getSpec (TTYPE (tree));
4721 /*------------------------------------------------------------------*/
4722 /*----------------------------*/
4723 /* return statement */
4724 /*----------------------------*/
4729 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4731 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4732 printFromToType (RTYPE(tree), currFunc->type->next);
4733 goto errorTreeReturn;
4736 if (IS_VOID (currFunc->type->next)
4738 !IS_VOID (RTYPE (tree)))
4740 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4741 goto errorTreeReturn;
4744 /* if there is going to be a casting required then add it */
4745 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4748 decorateType (newNode (CAST,
4749 newAst_LINK (copyLinkChain (currFunc->type->next)),
4759 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4761 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4762 goto errorTreeReturn;
4765 TTYPE (tree) = TETYPE (tree) = NULL;
4768 /*------------------------------------------------------------------*/
4769 /*----------------------------*/
4770 /* switch statement */
4771 /*----------------------------*/
4773 /* the switch value must be an integer */
4774 if (!IS_INTEGRAL (LTYPE (tree)))
4776 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4777 goto errorTreeReturn;
4780 TTYPE (tree) = TETYPE (tree) = NULL;
4783 /*------------------------------------------------------------------*/
4784 /*----------------------------*/
4786 /*----------------------------*/
4788 tree->left = backPatchLabels (tree->left,
4791 TTYPE (tree) = TETYPE (tree) = NULL;
4794 /*------------------------------------------------------------------*/
4795 /*----------------------------*/
4797 /*----------------------------*/
4800 AST_FOR (tree, initExpr) = decorateType (
4801 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4802 AST_FOR (tree, condExpr) = decorateType (
4803 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4804 AST_FOR (tree, loopExpr) = decorateType (
4805 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4807 /* if the for loop is reversible then
4808 reverse it otherwise do what we normally
4814 if (isLoopReversible (tree, &sym, &init, &end))
4815 return reverseLoop (tree, sym, init, end);
4817 return decorateType (createFor (AST_FOR (tree, trueLabel),
4818 AST_FOR (tree, continueLabel),
4819 AST_FOR (tree, falseLabel),
4820 AST_FOR (tree, condLabel),
4821 AST_FOR (tree, initExpr),
4822 AST_FOR (tree, condExpr),
4823 AST_FOR (tree, loopExpr),
4824 tree->left), RESULT_TYPE_NONE);
4827 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4828 "node PARAM shouldn't be processed here");
4829 /* but in processParams() */
4832 TTYPE (tree) = TETYPE (tree) = NULL;
4836 /* some error found this tree will be killed */
4838 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4839 tree->opval.op = NULLOP;
4845 /*-----------------------------------------------------------------*/
4846 /* sizeofOp - processes size of operation */
4847 /*-----------------------------------------------------------------*/
4849 sizeofOp (sym_link * type)
4854 /* make sure the type is complete and sane */
4855 checkTypeSanity(type, "(sizeof)");
4857 /* get the size and convert it to character */
4858 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4859 if (!size && !IS_VOID(type))
4860 werror (E_SIZEOF_INCOMPLETE_TYPE);
4862 /* now convert into value */
4863 return constVal (buff);
4867 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4868 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4869 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4870 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4871 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4872 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4873 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4875 /*-----------------------------------------------------------------*/
4876 /* backPatchLabels - change and or not operators to flow control */
4877 /*-----------------------------------------------------------------*/
4879 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4885 /* while-loops insert a label between the IFX and the condition,
4886 therefore look behind the label too */
4887 if (tree->opval.op == LABEL &&
4889 IS_ANDORNOT (tree->right))
4891 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4895 if (!(IS_ANDORNOT (tree)))
4898 /* if this an and */
4901 static int localLbl = 0;
4904 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4905 localLabel = newSymbol (buffer, NestLevel);
4907 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4909 /* if left is already a IFX then just change the if true label in that */
4910 if (!IS_IFX (tree->left))
4911 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4913 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4914 /* right is a IFX then just join */
4915 if (IS_IFX (tree->right))
4916 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4918 tree->right = createLabel (localLabel, tree->right);
4919 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4921 return newNode (NULLOP, tree->left, tree->right);
4924 /* if this is an or operation */
4927 static int localLbl = 0;
4930 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4931 localLabel = newSymbol (buffer, NestLevel);
4933 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4935 /* if left is already a IFX then just change the if true label in that */
4936 if (!IS_IFX (tree->left))
4937 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4939 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4940 /* right is a IFX then just join */
4941 if (IS_IFX (tree->right))
4942 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4944 tree->right = createLabel (localLabel, tree->right);
4945 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4947 return newNode (NULLOP, tree->left, tree->right);
4953 /* call with exchanged labels */
4954 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4956 /* if left isn't already a IFX */
4957 if (!IS_IFX (tree->left))
4959 tree->left = newNode (IFX, tree->left, NULL);
4960 tree->left->trueLabel = falseLabel;
4961 tree->left->falseLabel = trueLabel;
4968 tree->trueLabel = trueLabel;
4969 tree->falseLabel = falseLabel;
4976 /*-----------------------------------------------------------------*/
4977 /* createBlock - create expression tree for block */
4978 /*-----------------------------------------------------------------*/
4980 createBlock (symbol * decl, ast * body)
4984 /* if the block has nothing */
4988 ex = newNode (BLOCK, NULL, body);
4989 ex->values.sym = decl;
4992 ex->filename = NULL;
4997 /*-----------------------------------------------------------------*/
4998 /* createLabel - creates the expression tree for labels */
4999 /*-----------------------------------------------------------------*/
5001 createLabel (symbol * label, ast * stmnt)
5004 char name[SDCC_NAME_MAX + 1];
5007 /* must create fresh symbol if the symbol name */
5008 /* exists in the symbol table, since there can */
5009 /* be a variable with the same name as the labl */
5010 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5011 (csym->level == label->level))
5012 label = newSymbol (label->name, label->level);
5014 /* change the name before putting it in add _ */
5015 SNPRINTF(name, sizeof(name), "%s", label->name);
5017 /* put the label in the LabelSymbol table */
5018 /* but first check if a label of the same */
5020 if ((csym = findSym (LabelTab, NULL, name)))
5021 werror (E_DUPLICATE_LABEL, label->name);
5023 addSym (LabelTab, label, name, label->level, 0, 0);
5027 label->key = labelKey++;
5028 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5029 rValue->filename = NULL;
5035 /*-----------------------------------------------------------------*/
5036 /* createCase - generates the parsetree for a case statement */
5037 /*-----------------------------------------------------------------*/
5039 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5041 char caseLbl[SDCC_NAME_MAX + 1];
5045 /* if the switch statement does not exist */
5046 /* then case is out of context */
5049 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5053 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5054 /* if not a constant then error */
5055 if (!IS_LITERAL (caseVal->ftype))
5057 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5061 /* if not a integer than error */
5062 if (!IS_INTEGRAL (caseVal->ftype))
5064 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5068 /* find the end of the switch values chain */
5069 if (!(val = swStat->values.switchVals.swVals))
5070 swStat->values.switchVals.swVals = caseVal->opval.val;
5073 /* also order the cases according to value */
5075 int cVal = (int) ulFromVal (caseVal->opval.val);
5076 while (val && (int) ulFromVal (val) < cVal)
5082 /* if we reached the end then */
5085 pval->next = caseVal->opval.val;
5087 else if ((int) ulFromVal (val) == cVal)
5089 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5095 /* we found a value greater than */
5096 /* the current value we must add this */
5097 /* before the value */
5098 caseVal->opval.val->next = val;
5100 /* if this was the first in chain */
5101 if (swStat->values.switchVals.swVals == val)
5102 swStat->values.switchVals.swVals =
5105 pval->next = caseVal->opval.val;
5110 /* create the case label */
5111 SNPRINTF(caseLbl, sizeof(caseLbl),
5113 swStat->values.switchVals.swNum,
5114 (int) ulFromVal (caseVal->opval.val));
5116 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5117 rexpr->filename = 0;
5122 /*-----------------------------------------------------------------*/
5123 /* createDefault - creates the parse tree for the default statement */
5124 /*-----------------------------------------------------------------*/
5126 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5128 char defLbl[SDCC_NAME_MAX + 1];
5130 /* if the switch statement does not exist */
5131 /* then case is out of context */
5134 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5138 if (swStat->values.switchVals.swDefault)
5140 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5145 /* turn on the default flag */
5146 swStat->values.switchVals.swDefault = 1;
5148 /* create the label */
5149 SNPRINTF (defLbl, sizeof(defLbl),
5150 "_default_%d", swStat->values.switchVals.swNum);
5151 return createLabel (newSymbol (defLbl, 0), stmnt);
5154 /*-----------------------------------------------------------------*/
5155 /* createIf - creates the parsetree for the if statement */
5156 /*-----------------------------------------------------------------*/
5158 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5160 static int Lblnum = 0;
5162 symbol *ifTrue, *ifFalse, *ifEnd;
5164 /* if neither exists */
5165 if (!elseBody && !ifBody) {
5166 // if there are no side effects (i++, j() etc)
5167 if (!hasSEFcalls(condAst)) {
5172 /* create the labels */
5173 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5174 ifFalse = newSymbol (buffer, NestLevel);
5175 /* if no else body then end == false */
5180 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5181 ifEnd = newSymbol (buffer, NestLevel);
5184 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5185 ifTrue = newSymbol (buffer, NestLevel);
5189 /* attach the ifTrue label to the top of it body */
5190 ifBody = createLabel (ifTrue, ifBody);
5191 /* attach a goto end to the ifBody if else is present */
5194 ifBody = newNode (NULLOP, ifBody,
5196 newAst_VALUE (symbolVal (ifEnd)),
5198 /* put the elseLabel on the else body */
5199 elseBody = createLabel (ifFalse, elseBody);
5200 /* out the end at the end of the body */
5201 elseBody = newNode (NULLOP,
5203 createLabel (ifEnd, NULL));
5207 ifBody = newNode (NULLOP, ifBody,
5208 createLabel (ifFalse, NULL));
5210 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5211 if (IS_IFX (condAst))
5214 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5216 return newNode (NULLOP, ifTree,
5217 newNode (NULLOP, ifBody, elseBody));
5221 /*-----------------------------------------------------------------*/
5222 /* createDo - creates parse tree for do */
5225 /* _docontinue_n: */
5226 /* condition_expression +-> trueLabel -> _dobody_n */
5228 /* +-> falseLabel-> _dobreak_n */
5230 /*-----------------------------------------------------------------*/
5232 createDo (symbol * trueLabel, symbol * continueLabel,
5233 symbol * falseLabel, ast * condAst, ast * doBody)
5238 /* if the body does not exist then it is simple */
5241 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5242 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5243 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5244 doTree->trueLabel = continueLabel;
5245 doTree->falseLabel = NULL;
5247 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5251 /* otherwise we have a body */
5252 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5254 /* attach the body label to the top */
5255 doBody = createLabel (trueLabel, doBody);
5256 /* attach the continue label to end of body */
5257 doBody = newNode (NULLOP, doBody,
5258 createLabel (continueLabel, NULL));
5260 /* now put the break label at the end */
5261 if (IS_IFX (condAst))
5264 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5266 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5268 /* putting it together */
5269 return newNode (NULLOP, doBody, doTree);
5272 /*-----------------------------------------------------------------*/
5273 /* createFor - creates parse tree for 'for' statement */
5276 /* condExpr +-> trueLabel -> _forbody_n */
5278 /* +-> falseLabel-> _forbreak_n */
5281 /* _forcontinue_n: */
5283 /* goto _forcond_n ; */
5285 /*-----------------------------------------------------------------*/
5287 createFor (symbol * trueLabel, symbol * continueLabel,
5288 symbol * falseLabel, symbol * condLabel,
5289 ast * initExpr, ast * condExpr, ast * loopExpr,
5294 /* if loopexpression not present then we can generate it */
5295 /* the same way as a while */
5297 return newNode (NULLOP, initExpr,
5298 createWhile (trueLabel, continueLabel,
5299 falseLabel, condExpr, forBody));
5300 /* vanilla for statement */
5301 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5303 if (condExpr && !IS_IFX (condExpr))
5304 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5307 /* attach condition label to condition */
5308 condExpr = createLabel (condLabel, condExpr);
5310 /* attach body label to body */
5311 forBody = createLabel (trueLabel, forBody);
5313 /* attach continue to forLoop expression & attach */
5314 /* goto the forcond @ and of loopExpression */
5315 loopExpr = createLabel (continueLabel,
5319 newAst_VALUE (symbolVal (condLabel)),
5321 /* now start putting them together */
5322 forTree = newNode (NULLOP, initExpr, condExpr);
5323 forTree = newNode (NULLOP, forTree, forBody);
5324 forTree = newNode (NULLOP, forTree, loopExpr);
5325 /* finally add the break label */
5326 forTree = newNode (NULLOP, forTree,
5327 createLabel (falseLabel, NULL));
5331 /*-----------------------------------------------------------------*/
5332 /* createWhile - creates parse tree for while statement */
5333 /* the while statement will be created as follows */
5335 /* _while_continue_n: */
5336 /* condition_expression +-> trueLabel -> _while_boby_n */
5338 /* +-> falseLabel -> _while_break_n */
5339 /* _while_body_n: */
5341 /* goto _while_continue_n */
5342 /* _while_break_n: */
5343 /*-----------------------------------------------------------------*/
5345 createWhile (symbol * trueLabel, symbol * continueLabel,
5346 symbol * falseLabel, ast * condExpr, ast * whileBody)
5350 /* put the continue label */
5351 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5352 condExpr = createLabel (continueLabel, condExpr);
5353 condExpr->filename = NULL;
5354 condExpr->lineno = 0;
5356 /* put the body label in front of the body */
5357 whileBody = createLabel (trueLabel, whileBody);
5358 whileBody->filename = NULL;
5359 whileBody->lineno = 0;
5360 /* put a jump to continue at the end of the body */
5361 /* and put break label at the end of the body */
5362 whileBody = newNode (NULLOP,
5365 newAst_VALUE (symbolVal (continueLabel)),
5366 createLabel (falseLabel, NULL)));
5368 /* put it all together */
5369 if (IS_IFX (condExpr))
5370 whileTree = condExpr;
5373 whileTree = newNode (IFX, condExpr, NULL);
5374 /* put the true & false labels in place */
5375 whileTree->trueLabel = trueLabel;
5376 whileTree->falseLabel = falseLabel;
5379 return newNode (NULLOP, whileTree, whileBody);
5382 /*-----------------------------------------------------------------*/
5383 /* isShiftRightLitVal _BitAndLitVal - helper function */
5384 /*-----------------------------------------------------------------*/
5386 isShiftRightLitVal_BitAndLitVal (ast * tree)
5388 /* if this is not a bit and */
5389 if (!IS_BITAND (tree))
5392 /* will look for tree of the form
5393 ( expr >> litval2) & litval1 */
5394 if (!IS_AST_LIT_VALUE (tree->right))
5397 if (!IS_RIGHT_OP (tree->left))
5400 if (!IS_AST_LIT_VALUE (tree->left->right))
5403 return tree->left->left;
5406 /*-----------------------------------------------------------------*/
5407 /* isBitAndPowOf2 - helper function */
5408 /*-----------------------------------------------------------------*/
5410 isBitAndPow2 (ast * tree)
5412 /* if this is not a bit and */
5413 if (!IS_BITAND (tree))
5416 /* will look for tree of the form
5417 ( expr & (1 << litval) */
5418 if (!IS_AST_LIT_VALUE (tree->right))
5421 return powof2 (AST_ULONG_VALUE (tree->right));
5424 /*-----------------------------------------------------------------*/
5425 /* optimizeGetHbit - get highest order bit of the expression */
5426 /*-----------------------------------------------------------------*/
5428 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5433 expr = isShiftRightLitVal_BitAndLitVal(tree);
5436 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5437 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5438 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5441 if (!expr && (resultType == RESULT_TYPE_BIT))
5444 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5450 /* make sure the port supports GETHBIT */
5451 if (port->hasExtBitOp
5452 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5455 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5458 /*-----------------------------------------------------------------*/
5459 /* optimizeGetAbit - get a single bit of the expression */
5460 /*-----------------------------------------------------------------*/
5462 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5467 expr = isShiftRightLitVal_BitAndLitVal(tree);
5470 if (AST_ULONG_VALUE (tree->right) != 1)
5472 count = tree->left->right;
5474 if (!expr && (resultType == RESULT_TYPE_BIT))
5476 int p2 = isBitAndPow2 (tree);
5480 count = newAst_VALUE (valueFromLit (p2));
5486 /* make sure the port supports GETABIT */
5487 if (port->hasExtBitOp
5488 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5491 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5495 /*-----------------------------------------------------------------*/
5496 /* optimizeGetByte - get a byte of the expression */
5497 /*-----------------------------------------------------------------*/
5499 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5505 expr = isShiftRightLitVal_BitAndLitVal(tree);
5508 i = AST_ULONG_VALUE (tree->left->right);
5509 count = tree->left->right;
5510 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5513 if (!expr && resultType == RESULT_TYPE_CHAR)
5515 /* if this is a right shift over a multiple of 8 */
5516 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5518 i = AST_ULONG_VALUE (tree->right);
5519 count = tree->right;
5523 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5526 /* make sure the port supports GETBYTE */
5527 if (port->hasExtBitOp
5528 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5531 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5534 /*-----------------------------------------------------------------*/
5535 /* optimizeGetWord - get two bytes of the expression */
5536 /*-----------------------------------------------------------------*/
5538 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5544 expr = isShiftRightLitVal_BitAndLitVal(tree);
5547 i = AST_ULONG_VALUE (tree->left->right);
5548 count = tree->left->right;
5549 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5552 if (!expr && resultType == RESULT_TYPE_INT)
5554 /* if this is a right shift over a multiple of 8 */
5555 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5557 i = AST_ULONG_VALUE (tree->right);
5558 count = tree->right;
5562 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5565 /* make sure the port supports GETWORD */
5566 if (port->hasExtBitOp
5567 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5570 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5573 /*-----------------------------------------------------------------*/
5574 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5575 /*-----------------------------------------------------------------*/
5577 optimizeRRCRLC (ast * root)
5579 /* will look for trees of the form
5580 (?expr << 1) | (?expr >> 7) or
5581 (?expr >> 7) | (?expr << 1) will make that
5582 into a RLC : operation ..
5584 (?expr >> 1) | (?expr << 7) or
5585 (?expr << 7) | (?expr >> 1) will make that
5586 into a RRC operation
5587 note : by 7 I mean (number of bits required to hold the
5589 /* if the root operation is not a | operation then not */
5590 if (!IS_BITOR (root))
5593 /* I have to think of a better way to match patterns this sucks */
5594 /* that aside let's start looking for the first case : I use a
5595 negative check a lot to improve the efficiency */
5596 /* (?expr << 1) | (?expr >> 7) */
5597 if (IS_LEFT_OP (root->left) &&
5598 IS_RIGHT_OP (root->right))
5601 if (!SPEC_USIGN (TETYPE (root->left->left)))
5604 if (!IS_AST_LIT_VALUE (root->left->right) ||
5605 !IS_AST_LIT_VALUE (root->right->right))
5608 /* make sure it is the same expression */
5609 if (!isAstEqual (root->left->left,
5613 if (AST_ULONG_VALUE (root->left->right) != 1)
5616 if (AST_ULONG_VALUE (root->right->right) !=
5617 (getSize (TTYPE (root->left->left)) * 8 - 1))
5620 /* make sure the port supports RLC */
5621 if (port->hasExtBitOp
5622 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5625 /* whew got the first case : create the AST */
5626 return newNode (RLC, root->left->left, NULL);
5630 /* check for second case */
5631 /* (?expr >> 7) | (?expr << 1) */
5632 if (IS_LEFT_OP (root->right) &&
5633 IS_RIGHT_OP (root->left))
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 symbol */
5644 if (!isAstEqual (root->left->left,
5648 if (AST_ULONG_VALUE (root->right->right) != 1)
5651 if (AST_ULONG_VALUE (root->left->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);
5666 /* third case for RRC */
5667 /* (?symbol >> 1) | (?symbol << 7) */
5668 if (IS_LEFT_OP (root->right) &&
5669 IS_RIGHT_OP (root->left))
5672 if (!SPEC_USIGN (TETYPE (root->left->left)))
5675 if (!IS_AST_LIT_VALUE (root->left->right) ||
5676 !IS_AST_LIT_VALUE (root->right->right))
5679 /* make sure it is the same symbol */
5680 if (!isAstEqual (root->left->left,
5684 if (AST_ULONG_VALUE (root->left->right) != 1)
5687 if (AST_ULONG_VALUE (root->right->right) !=
5688 (getSize (TTYPE (root->left->left)) * 8 - 1))
5691 /* make sure the port supports RRC */
5692 if (port->hasExtBitOp
5693 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5696 /* whew got the first case : create the AST */
5697 return newNode (RRC, root->left->left, NULL);
5701 /* fourth and last case for now */
5702 /* (?symbol << 7) | (?symbol >> 1) */
5703 if (IS_RIGHT_OP (root->right) &&
5704 IS_LEFT_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->right->right) != 1)
5722 if (AST_ULONG_VALUE (root->left->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 /* not found return root */
5740 /*-----------------------------------------------------------------*/
5741 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5742 /*-----------------------------------------------------------------*/
5744 optimizeSWAP (ast * root)
5746 /* will look for trees of the form
5747 (?expr << 4) | (?expr >> 4) or
5748 (?expr >> 4) | (?expr << 4) will make that
5749 into a SWAP : operation ..
5750 note : by 4 I mean (number of bits required to hold the
5752 /* if the root operation is not a | operation then not */
5753 if (!IS_BITOR (root))
5756 /* (?expr << 4) | (?expr >> 4) */
5757 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5758 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5761 if (!SPEC_USIGN (TETYPE (root->left->left)))
5764 if (!IS_AST_LIT_VALUE (root->left->right) ||
5765 !IS_AST_LIT_VALUE (root->right->right))
5768 /* make sure it is the same expression */
5769 if (!isAstEqual (root->left->left,
5773 if (AST_ULONG_VALUE (root->left->right) !=
5774 (getSize (TTYPE (root->left->left)) * 4))
5777 if (AST_ULONG_VALUE (root->right->right) !=
5778 (getSize (TTYPE (root->left->left)) * 4))
5781 /* make sure the port supports SWAP */
5782 if (port->hasExtBitOp
5783 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5786 /* found it : create the AST */
5787 return newNode (SWAP, root->left->left, NULL);
5791 /* not found return root */
5795 /*-----------------------------------------------------------------*/
5796 /* optimizeCompare - optimizes compares for bit variables */
5797 /*-----------------------------------------------------------------*/
5799 optimizeCompare (ast * root)
5801 ast *optExpr = NULL;
5804 unsigned int litValue;
5806 /* if nothing then return nothing */
5810 /* if not a compare op then do leaves */
5811 if (!IS_COMPARE_OP (root))
5813 root->left = optimizeCompare (root->left);
5814 root->right = optimizeCompare (root->right);
5818 /* if left & right are the same then depending
5819 of the operation do */
5820 if (isAstEqual (root->left, root->right))
5822 switch (root->opval.op)
5827 optExpr = newAst_VALUE (constCharVal (0));
5832 optExpr = newAst_VALUE (constCharVal (1));
5836 return decorateType (optExpr, RESULT_TYPE_NONE);
5839 vleft = (root->left->type == EX_VALUE ?
5840 root->left->opval.val : NULL);
5842 vright = (root->right->type == EX_VALUE ?
5843 root->right->opval.val : NULL);
5845 /* if left is a BITVAR in BITSPACE */
5846 /* and right is a LITERAL then */
5847 /* optimize else do nothing */
5848 if (vleft && vright &&
5849 IS_BITVAR (vleft->etype) &&
5850 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5851 IS_LITERAL (vright->etype))
5854 /* if right side > 1 then comparison may never succeed */
5855 if ((litValue = (int) ulFromVal (vright)) > 1)
5857 werror (W_BAD_COMPARE);
5863 switch (root->opval.op)
5865 case '>': /* bit value greater than 1 cannot be */
5866 werror (W_BAD_COMPARE);
5870 case '<': /* bit value < 1 means 0 */
5872 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5875 case LE_OP: /* bit value <= 1 means no check */
5876 optExpr = newAst_VALUE (vright);
5879 case GE_OP: /* bit value >= 1 means only check for = */
5881 optExpr = newAst_VALUE (vleft);
5886 { /* literal is zero */
5887 switch (root->opval.op)
5889 case '<': /* bit value < 0 cannot be */
5890 werror (W_BAD_COMPARE);
5894 case '>': /* bit value > 0 means 1 */
5896 optExpr = newAst_VALUE (vleft);
5899 case LE_OP: /* bit value <= 0 means no check */
5900 case GE_OP: /* bit value >= 0 means no check */
5901 werror (W_BAD_COMPARE);
5905 case EQ_OP: /* bit == 0 means ! of bit */
5906 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5910 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5911 } /* end-of-if of BITVAR */
5917 /*-----------------------------------------------------------------*/
5918 /* addSymToBlock : adds the symbol to the first block we find */
5919 /*-----------------------------------------------------------------*/
5921 addSymToBlock (symbol * sym, ast * tree)
5923 /* reached end of tree or a leaf */
5924 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5928 if (IS_AST_OP (tree) &&
5929 tree->opval.op == BLOCK)
5932 symbol *lsym = copySymbol (sym);
5934 lsym->next = AST_VALUES (tree, sym);
5935 AST_VALUES (tree, sym) = lsym;
5939 addSymToBlock (sym, tree->left);
5940 addSymToBlock (sym, tree->right);
5943 /*-----------------------------------------------------------------*/
5944 /* processRegParms - do processing for register parameters */
5945 /*-----------------------------------------------------------------*/
5947 processRegParms (value * args, ast * body)
5951 if (IS_REGPARM (args->etype))
5952 addSymToBlock (args->sym, body);
5957 /*-----------------------------------------------------------------*/
5958 /* resetParmKey - resets the operandkeys for the symbols */
5959 /*-----------------------------------------------------------------*/
5960 DEFSETFUNC (resetParmKey)
5973 /*------------------------------------------------------------------*/
5974 /* fixupInlineLabel - change a label in an inlined function so that */
5975 /* it is always unique no matter how many times */
5976 /* the function is inlined. */
5977 /*------------------------------------------------------------------*/
5979 fixupInlineLabel (symbol * sym)
5981 char name[SDCC_NAME_MAX + 1];
5983 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5984 strcpy (sym->name, name);
5988 /*------------------------------------------------------------------*/
5989 /* copyAstLoc - copy location information (file, line, block, etc.) */
5990 /* from one ast node to another */
5991 /*------------------------------------------------------------------*/
5993 copyAstLoc (ast * dest, ast * src)
5995 dest->filename = src->filename;
5996 dest->lineno = src->lineno;
5997 dest->level = src->level;
5998 dest->block = src->block;
5999 dest->seqPoint = src->seqPoint;
6004 /*-----------------------------------------------------------------*/
6005 /* fixupInline - perform various fixups on an inline function tree */
6006 /* to take into account that it is no longer a */
6007 /* stand-alone function. */
6008 /*-----------------------------------------------------------------*/
6010 fixupInline (ast * tree, int level)
6012 tree->block = currBlockno;
6014 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6021 /* Add any declared variables back into the symbol table */
6022 decls = tree->values.sym;
6025 decls->level = level;
6026 decls->block = currBlockno;
6027 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6028 decls = decls->next;
6032 tree->level = level;
6034 /* Update symbols */
6035 if (IS_AST_VALUE (tree) &&
6036 tree->opval.val->sym)
6038 symbol * sym = tree->opval.val->sym;
6041 sym->block = currBlockno;
6044 SYM_SPIL_LOC (sym) = NULL;
6047 /* If the symbol is a label, we need to renumber it */
6049 fixupInlineLabel (sym);
6052 /* Update IFX target labels */
6053 if (tree->type == EX_OP && tree->opval.op == IFX)
6055 if (tree->trueLabel)
6056 fixupInlineLabel (tree->trueLabel);
6057 if (tree->falseLabel)
6058 fixupInlineLabel (tree->falseLabel);
6061 /* Replace RETURN with optional assignment and a GOTO to the end */
6062 /* of the inlined function */
6063 if (tree->type == EX_OP && tree->opval.op == RETURN)
6065 ast * assignTree = NULL;
6068 if (inlineState.retsym && tree->right)
6070 assignTree = newNode ('=',
6071 newAst_VALUE (symbolVal (inlineState.retsym)),
6073 copyAstLoc (assignTree, tree);
6076 gotoTree = newNode (GOTO,
6077 newAst_VALUE (symbolVal (inlineState.retlab)),
6079 copyAstLoc (gotoTree, tree);
6081 tree->opval.op = NULLOP;
6082 tree->left = assignTree;
6083 tree->right = gotoTree;
6086 /* Update any children */
6088 fixupInline (tree->left, level);
6090 fixupInline (tree->right, level);
6092 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6094 symbol * label = tree->left->opval.val->sym;
6096 label->key = labelKey++;
6097 /* Add this label back into the symbol table */
6098 addSym (LabelTab, label, label->name, label->level, 0, 0);
6102 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6108 /*-----------------------------------------------------------------*/
6109 /* inlineAddDecl - add a variable declaration to an ast block. It */
6110 /* is also added to the symbol table if addSymTab */
6112 /*-----------------------------------------------------------------*/
6114 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6117 SYM_SPIL_LOC (sym) = NULL;
6121 symbol **decl = &(block->values.sym);
6123 sym->level = block->level;
6124 sym->block = block->block;
6128 if (strcmp ((*decl)->name, sym->name) == 0)
6130 decl = &( (*decl)->next );
6136 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6142 /*-----------------------------------------------------------------*/
6143 /* inlineTempVar - create a temporary variable for inlining */
6144 /*-----------------------------------------------------------------*/
6146 inlineTempVar (sym_link * type, int level)
6150 sym = newSymbol (genSymName(level), level );
6151 sym->type = copyLinkChain (type);
6152 sym->etype = getSpec(sym->type);
6153 SPEC_SCLS (sym->etype) = S_AUTO;
6154 SPEC_OCLS (sym->etype) = NULL;
6155 SPEC_EXTR (sym->etype) = 0;
6156 SPEC_STAT (sym->etype) = 0;
6157 if IS_SPEC (sym->type)
6158 SPEC_VOLATILE (sym->type) = 0;
6160 DCL_PTR_VOLATILE (sym->type) = 0;
6161 SPEC_ABSA (sym->etype) = 0;
6167 /*-----------------------------------------------------------------*/
6168 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6169 /*-----------------------------------------------------------------*/
6171 inlineFindParmRecurse (ast * parms, int *index)
6176 if (parms->type == EX_OP && parms->opval.op == PARAM)
6180 p=inlineFindParmRecurse (parms->left, index);
6183 p=inlineFindParmRecurse (parms->right, index);
6194 /*-----------------------------------------------------------------*/
6195 /* inlineFindParm - search an ast tree of parameters to find one */
6196 /* at a particular index (0=first parameter). */
6197 /* Returns NULL if not found. */
6198 /*-----------------------------------------------------------------*/
6200 inlineFindParm (ast * parms, int index)
6202 return inlineFindParmRecurse (parms, &index);
6205 /*-----------------------------------------------------------------*/
6206 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6207 /*-----------------------------------------------------------------*/
6209 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6216 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6217 if (tempBlockno > maxBlockno)
6218 maxBlockno = tempBlockno;
6220 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6221 if (tempBlockno > maxBlockno)
6222 maxBlockno = tempBlockno;
6224 if (tree->block > maxBlockno)
6225 maxBlockno = tree->block;
6232 /*-----------------------------------------------------------------*/
6233 /* expandInlineFuncs - replace calls to inline functions with the */
6234 /* function itself */
6235 /*-----------------------------------------------------------------*/
6237 expandInlineFuncs (ast * tree, ast * block)
6239 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6240 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6242 symbol * func = tree->left->opval.val->sym;
6245 /* The symbol is probably not bound yet, so find the real one */
6246 csym = findSymWithLevel (SymbolTab, func);
6250 /* Is this an inline function that we can inline? */
6251 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6253 symbol * retsym = NULL;
6261 /* Generate a label for the inlined function to branch to */
6262 /* in case it contains a return statement */
6263 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6266 inlineState.retlab = retlab;
6268 /* Build the subtree for the inlined function in the form: */
6269 /* { //inlinetree block */
6270 /* { //inlinetree2 block */
6271 /* inline_function_code; */
6275 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6276 copyAstLoc (temptree, tree);
6277 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6278 copyAstLoc (temptree, tree);
6279 temptree = newNode (BLOCK, NULL, temptree);
6280 copyAstLoc (temptree, tree);
6281 inlinetree2 = temptree;
6282 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6283 copyAstLoc (inlinetree, tree);
6285 /* To pass parameters to the inlined function, we need some */
6286 /* intermediate variables. This avoids scoping problems */
6287 /* when the parameter declaration names are used differently */
6288 /* during the function call. For example, a function */
6289 /* declared as func(int x, int y) but called as func(y,x). */
6290 /* { //inlinetree block */
6291 /* type1 temparg1; */
6293 /* typen tempargn; */
6294 /* temparg1 = argument1; */
6296 /* tempargn = argumentn; */
6297 /* { //inlinetree2 block */
6301 /* param1 = temparg1; */
6303 /* paramn = tempargn; */
6304 /* inline_function_code; */
6308 args = FUNC_ARGS (func->type);
6315 ast * passedarg = inlineFindParm (tree->right, argIndex);
6319 werror(E_TOO_FEW_PARMS);
6323 temparg = inlineTempVar (args->sym->type, tree->level+1);
6324 inlineAddDecl (temparg, inlinetree, FALSE);
6326 assigntree = newNode ('=',
6327 newAst_VALUE (symbolVal (temparg)),
6329 inlinetree->right = newNode (NULLOP,
6333 parm = copySymbol (args->sym);
6334 inlineAddDecl (parm, inlinetree2, FALSE);
6337 assigntree = newNode ('=',
6338 newAst_VALUE (symbolVal (parm)),
6339 newAst_VALUE (symbolVal (temparg)));
6340 inlinetree2->right = newNode (NULLOP,
6342 inlinetree2->right);
6349 /* Handle the return type */
6350 if (!IS_VOID (func->type->next))
6352 /* Create a temporary symbol to hold the return value and */
6353 /* join it with the inlined function using the comma */
6354 /* operator. The fixupInline function will take care of */
6355 /* changing return statements into assignments to retsym. */
6356 /* (parameter passing and return label omitted for clarity) */
6357 /* rettype retsym; */
6359 /* {{inline_function_code}}, retsym */
6361 retsym = inlineTempVar (func->type->next, tree->level);
6362 inlineAddDecl (retsym, block, TRUE);
6364 tree->opval.op = ',';
6365 tree->left = inlinetree;
6366 tree->right = newAst_VALUE (symbolVal (retsym));
6370 tree->opval.op = NULLOP;
6372 tree->right = inlinetree;
6374 inlineState.retsym = retsym;
6376 /* Renumber the various internal counters on the inlined */
6377 /* function's tree nodes and symbols. Add the inlined */
6378 /* function's local variables to the appropriate scope(s). */
6379 /* Convert inlined return statements to an assignment to */
6380 /* retsym (if needed) and a goto retlab. */
6381 fixupInline (inlinetree, inlinetree->level);
6382 inlineState.count++;
6387 /* Recursively continue to search for functions to inline. */
6388 if (IS_AST_OP (tree))
6390 if (tree->opval.op == BLOCK)
6394 expandInlineFuncs (tree->left, block);
6396 expandInlineFuncs (tree->right, block);
6401 /*-----------------------------------------------------------------*/
6402 /* createFunction - This is the key node that calls the iCode for */
6403 /* generating the code for a function. Note code */
6404 /* is generated function by function, later when */
6405 /* add inter-procedural analysis this will change */
6406 /*-----------------------------------------------------------------*/
6408 createFunction (symbol * name, ast * body)
6414 iCode *piCode = NULL;
6417 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6418 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6420 /* if check function return 0 then some problem */
6421 if (checkFunction (name, NULL) == 0)
6424 /* create a dummy block if none exists */
6426 body = newNode (BLOCK, NULL, NULL);
6430 /* check if the function name already in the symbol table */
6431 if ((csym = findSym (SymbolTab, NULL, name->name)))
6434 /* special case for compiler defined functions
6435 we need to add the name to the publics list : this
6436 actually means we are now compiling the compiler
6440 addSet (&publics, name);
6445 addSymChain (&name);
6446 allocVariables (name);
6448 name->lastLine = lexLineno;
6451 /* set the stack pointer */
6452 stackPtr = -port->stack.direction * port->stack.call_overhead;
6455 if (IFFUNC_ISISR (name->type))
6456 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6458 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6460 if (options.useXstack)
6461 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6463 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6466 fetype = getSpec (name->type); /* get the specifier for the function */
6467 /* if this is a reentrant function then */
6468 if (IFFUNC_ISREENT (name->type))
6471 inlineState.count = 0;
6472 savedBlockno = currBlockno;
6473 currBlockno = inlineFindMaxBlockno (body, 0);
6474 expandInlineFuncs (body, NULL);
6475 currBlockno = savedBlockno;
6477 if (FUNC_ISINLINE (name->type))
6478 name->funcTree = copyAst (body);
6480 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6482 /* do processing for parameters that are passed in registers */
6483 processRegParms (FUNC_ARGS(name->type), body);
6485 /* set the stack pointer */
6489 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6491 /* allocate & autoinit the block variables */
6492 processBlockVars (body, &stack, ALLOCATE);
6494 /* name needs to be mangled */
6495 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6497 body = resolveSymbols (body); /* resolve the symbols */
6498 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6500 /* save the stack information */
6501 if (options.useXstack)
6502 name->xstack = SPEC_STAK (fetype) = stack;
6504 name->stack = SPEC_STAK (fetype) = stack;
6506 ex = newAst_VALUE (symbolVal (name)); /* create name */
6507 ex = newNode (FUNCTION, ex, body);
6508 ex->values.args = FUNC_ARGS(name->type);
6510 if (options.dump_tree)
6515 /* Do not generate code for inline functions unless extern also. */
6517 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6520 /* Temporary hack: always generate code for static inline functions. */
6521 /* Ideally static inline functions should only be generated if needed. */
6522 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6526 /* create the node & generate intermediate code */
6528 codeOutBuf = &code->oBuf;
6529 piCode = iCodeFromAst (ex);
6530 name->generated = 1;
6535 eBBlockFromiCode (piCode);
6537 /* if there are any statics then do them */
6540 GcurMemmap = statsg;
6541 codeOutBuf = &statsg->oBuf;
6542 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6548 /* dealloc the block variables */
6549 processBlockVars (body, &stack, DEALLOCATE);
6550 outputDebugStackSymbols();
6551 /* deallocate paramaters */
6552 deallocParms (FUNC_ARGS(name->type));
6554 if (IFFUNC_ISREENT (name->type))
6557 /* we are done freeup memory & cleanup */
6559 if (port->reset_labelKey) labelKey = 1;
6561 FUNC_HASBODY(name->type) = 1;
6562 addSet (&operKeyReset, name);
6563 applyToSet (operKeyReset, resetParmKey);
6568 cleanUpLevel (LabelTab, 0);
6569 cleanUpBlock (StructTab, 1);
6570 cleanUpBlock (TypedefTab, 1);
6572 xstack->syms = NULL;
6573 istack->syms = NULL;
6578 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6579 /*-----------------------------------------------------------------*/
6580 /* ast_print : prints the ast (for debugging purposes) */
6581 /*-----------------------------------------------------------------*/
6583 void ast_print (ast * tree, FILE *outfile, int indent)
6588 /* can print only decorated trees */
6589 if (!tree->decorated) return;
6591 /* if any child is an error | this one is an error do nothing */
6592 if (tree->isError ||
6593 (tree->left && tree->left->isError) ||
6594 (tree->right && tree->right->isError)) {
6595 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6599 /* print the line */
6600 /* if not block & function */
6601 if (tree->type == EX_OP &&
6602 (tree->opval.op != FUNCTION &&
6603 tree->opval.op != BLOCK &&
6604 tree->opval.op != NULLOP)) {
6607 if (tree->opval.op == FUNCTION) {
6609 value *args=FUNC_ARGS(tree->left->opval.val->type);
6610 fprintf(outfile,"FUNCTION (%s=%p) type (",
6611 tree->left->opval.val->name, tree);
6612 printTypeChain (tree->left->opval.val->type->next,outfile);
6613 fprintf(outfile,") args (");
6616 fprintf (outfile, ", ");
6618 printTypeChain (args ? args->type : NULL, outfile);
6620 args= args ? args->next : NULL;
6622 fprintf(outfile,")\n");
6623 ast_print(tree->left,outfile,indent);
6624 ast_print(tree->right,outfile,indent);
6627 if (tree->opval.op == BLOCK) {
6628 symbol *decls = tree->values.sym;
6629 INDENT(indent,outfile);
6630 fprintf(outfile,"{\n");
6632 INDENT(indent+2,outfile);
6633 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6634 decls->name, decls);
6635 printTypeChain(decls->type,outfile);
6636 fprintf(outfile,")\n");
6638 decls = decls->next;
6640 ast_print(tree->right,outfile,indent+2);
6641 INDENT(indent,outfile);
6642 fprintf(outfile,"}\n");
6645 if (tree->opval.op == NULLOP) {
6646 ast_print(tree->left,outfile,indent);
6647 ast_print(tree->right,outfile,indent);
6650 INDENT(indent,outfile);
6652 /*------------------------------------------------------------------*/
6653 /*----------------------------*/
6654 /* leaf has been reached */
6655 /*----------------------------*/
6656 /* if this is of type value */
6657 /* just get the type */
6658 if (tree->type == EX_VALUE) {
6660 if (IS_LITERAL (tree->opval.val->etype)) {
6661 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6662 if (SPEC_USIGN (tree->opval.val->etype))
6663 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6665 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6666 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6667 floatFromVal(tree->opval.val));
6668 } else if (tree->opval.val->sym) {
6669 /* if the undefined flag is set then give error message */
6670 if (tree->opval.val->sym->undefined) {
6671 fprintf(outfile,"UNDEFINED SYMBOL ");
6673 fprintf(outfile,"SYMBOL ");
6675 fprintf(outfile,"(%s=%p @ %p)",
6676 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6679 fprintf(outfile," type (");
6680 printTypeChain(tree->ftype,outfile);
6681 fprintf(outfile,")\n");
6683 fprintf(outfile,"\n");
6688 /* if type link for the case of cast */
6689 if (tree->type == EX_LINK) {
6690 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6691 printTypeChain(tree->opval.lnk,outfile);
6692 fprintf(outfile,")\n");
6697 /* depending on type of operator do */
6699 switch (tree->opval.op) {
6700 /*------------------------------------------------------------------*/
6701 /*----------------------------*/
6703 /*----------------------------*/
6705 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6706 printTypeChain(tree->ftype,outfile);
6707 fprintf(outfile,")\n");
6708 ast_print(tree->left,outfile,indent+2);
6709 ast_print(tree->right,outfile,indent+2);
6712 /*------------------------------------------------------------------*/
6713 /*----------------------------*/
6715 /*----------------------------*/
6717 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6718 printTypeChain(tree->ftype,outfile);
6719 fprintf(outfile,")\n");
6720 ast_print(tree->left,outfile,indent+2);
6721 ast_print(tree->right,outfile,indent+2);
6724 /*------------------------------------------------------------------*/
6725 /*----------------------------*/
6726 /* struct/union pointer */
6727 /*----------------------------*/
6729 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6730 printTypeChain(tree->ftype,outfile);
6731 fprintf(outfile,")\n");
6732 ast_print(tree->left,outfile,indent+2);
6733 ast_print(tree->right,outfile,indent+2);
6736 /*------------------------------------------------------------------*/
6737 /*----------------------------*/
6738 /* ++/-- operation */
6739 /*----------------------------*/
6742 fprintf(outfile,"post-");
6744 fprintf(outfile,"pre-");
6745 fprintf(outfile,"INC_OP (%p) type (",tree);
6746 printTypeChain(tree->ftype,outfile);
6747 fprintf(outfile,")\n");
6748 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6749 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6754 fprintf(outfile,"post-");
6756 fprintf(outfile,"pre-");
6757 fprintf(outfile,"DEC_OP (%p) type (",tree);
6758 printTypeChain(tree->ftype,outfile);
6759 fprintf(outfile,")\n");
6760 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6761 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6764 /*------------------------------------------------------------------*/
6765 /*----------------------------*/
6767 /*----------------------------*/
6770 fprintf(outfile,"& (%p) type (",tree);
6771 printTypeChain(tree->ftype,outfile);
6772 fprintf(outfile,")\n");
6773 ast_print(tree->left,outfile,indent+2);
6774 ast_print(tree->right,outfile,indent+2);
6776 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6777 printTypeChain(tree->ftype,outfile);
6778 fprintf(outfile,")\n");
6779 ast_print(tree->left,outfile,indent+2);
6780 ast_print(tree->right,outfile,indent+2);
6783 /*----------------------------*/
6785 /*----------------------------*/
6787 fprintf(outfile,"OR (%p) type (",tree);
6788 printTypeChain(tree->ftype,outfile);
6789 fprintf(outfile,")\n");
6790 ast_print(tree->left,outfile,indent+2);
6791 ast_print(tree->right,outfile,indent+2);
6793 /*------------------------------------------------------------------*/
6794 /*----------------------------*/
6796 /*----------------------------*/
6798 fprintf(outfile,"XOR (%p) type (",tree);
6799 printTypeChain(tree->ftype,outfile);
6800 fprintf(outfile,")\n");
6801 ast_print(tree->left,outfile,indent+2);
6802 ast_print(tree->right,outfile,indent+2);
6805 /*------------------------------------------------------------------*/
6806 /*----------------------------*/
6808 /*----------------------------*/
6810 fprintf(outfile,"DIV (%p) type (",tree);
6811 printTypeChain(tree->ftype,outfile);
6812 fprintf(outfile,")\n");
6813 ast_print(tree->left,outfile,indent+2);
6814 ast_print(tree->right,outfile,indent+2);
6816 /*------------------------------------------------------------------*/
6817 /*----------------------------*/
6819 /*----------------------------*/
6821 fprintf(outfile,"MOD (%p) type (",tree);
6822 printTypeChain(tree->ftype,outfile);
6823 fprintf(outfile,")\n");
6824 ast_print(tree->left,outfile,indent+2);
6825 ast_print(tree->right,outfile,indent+2);
6828 /*------------------------------------------------------------------*/
6829 /*----------------------------*/
6830 /* address dereference */
6831 /*----------------------------*/
6832 case '*': /* can be unary : if right is null then unary operation */
6834 fprintf(outfile,"DEREF (%p) type (",tree);
6835 printTypeChain(tree->ftype,outfile);
6836 fprintf(outfile,")\n");
6837 ast_print(tree->left,outfile,indent+2);
6840 /*------------------------------------------------------------------*/
6841 /*----------------------------*/
6842 /* multiplication */
6843 /*----------------------------*/
6844 fprintf(outfile,"MULT (%p) type (",tree);
6845 printTypeChain(tree->ftype,outfile);
6846 fprintf(outfile,")\n");
6847 ast_print(tree->left,outfile,indent+2);
6848 ast_print(tree->right,outfile,indent+2);
6852 /*------------------------------------------------------------------*/
6853 /*----------------------------*/
6854 /* unary '+' operator */
6855 /*----------------------------*/
6859 fprintf(outfile,"UPLUS (%p) type (",tree);
6860 printTypeChain(tree->ftype,outfile);
6861 fprintf(outfile,")\n");
6862 ast_print(tree->left,outfile,indent+2);
6864 /*------------------------------------------------------------------*/
6865 /*----------------------------*/
6867 /*----------------------------*/
6868 fprintf(outfile,"ADD (%p) type (",tree);
6869 printTypeChain(tree->ftype,outfile);
6870 fprintf(outfile,")\n");
6871 ast_print(tree->left,outfile,indent+2);
6872 ast_print(tree->right,outfile,indent+2);
6875 /*------------------------------------------------------------------*/
6876 /*----------------------------*/
6878 /*----------------------------*/
6879 case '-': /* can be unary */
6881 fprintf(outfile,"UMINUS (%p) type (",tree);
6882 printTypeChain(tree->ftype,outfile);
6883 fprintf(outfile,")\n");
6884 ast_print(tree->left,outfile,indent+2);
6886 /*------------------------------------------------------------------*/
6887 /*----------------------------*/
6889 /*----------------------------*/
6890 fprintf(outfile,"SUB (%p) type (",tree);
6891 printTypeChain(tree->ftype,outfile);
6892 fprintf(outfile,")\n");
6893 ast_print(tree->left,outfile,indent+2);
6894 ast_print(tree->right,outfile,indent+2);
6897 /*------------------------------------------------------------------*/
6898 /*----------------------------*/
6900 /*----------------------------*/
6902 fprintf(outfile,"COMPL (%p) type (",tree);
6903 printTypeChain(tree->ftype,outfile);
6904 fprintf(outfile,")\n");
6905 ast_print(tree->left,outfile,indent+2);
6907 /*------------------------------------------------------------------*/
6908 /*----------------------------*/
6910 /*----------------------------*/
6912 fprintf(outfile,"NOT (%p) type (",tree);
6913 printTypeChain(tree->ftype,outfile);
6914 fprintf(outfile,")\n");
6915 ast_print(tree->left,outfile,indent+2);
6917 /*------------------------------------------------------------------*/
6918 /*----------------------------*/
6920 /*----------------------------*/
6922 fprintf(outfile,"RRC (%p) type (",tree);
6923 printTypeChain(tree->ftype,outfile);
6924 fprintf(outfile,")\n");
6925 ast_print(tree->left,outfile,indent+2);
6929 fprintf(outfile,"RLC (%p) type (",tree);
6930 printTypeChain(tree->ftype,outfile);
6931 fprintf(outfile,")\n");
6932 ast_print(tree->left,outfile,indent+2);
6935 fprintf(outfile,"SWAP (%p) type (",tree);
6936 printTypeChain(tree->ftype,outfile);
6937 fprintf(outfile,")\n");
6938 ast_print(tree->left,outfile,indent+2);
6941 fprintf(outfile,"GETHBIT (%p) type (",tree);
6942 printTypeChain(tree->ftype,outfile);
6943 fprintf(outfile,")\n");
6944 ast_print(tree->left,outfile,indent+2);
6947 fprintf(outfile,"GETABIT (%p) type (",tree);
6948 printTypeChain(tree->ftype,outfile);
6949 fprintf(outfile,")\n");
6950 ast_print(tree->left,outfile,indent+2);
6951 ast_print(tree->right,outfile,indent+2);
6954 fprintf(outfile,"GETBYTE (%p) type (",tree);
6955 printTypeChain(tree->ftype,outfile);
6956 fprintf(outfile,")\n");
6957 ast_print(tree->left,outfile,indent+2);
6958 ast_print(tree->right,outfile,indent+2);
6961 fprintf(outfile,"GETWORD (%p) type (",tree);
6962 printTypeChain(tree->ftype,outfile);
6963 fprintf(outfile,")\n");
6964 ast_print(tree->left,outfile,indent+2);
6965 ast_print(tree->right,outfile,indent+2);
6968 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6969 printTypeChain(tree->ftype,outfile);
6970 fprintf(outfile,")\n");
6971 ast_print(tree->left,outfile,indent+2);
6972 ast_print(tree->right,outfile,indent+2);
6975 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6976 printTypeChain(tree->ftype,outfile);
6977 fprintf(outfile,")\n");
6978 ast_print(tree->left,outfile,indent+2);
6979 ast_print(tree->right,outfile,indent+2);
6981 /*------------------------------------------------------------------*/
6982 /*----------------------------*/
6984 /*----------------------------*/
6985 case CAST: /* change the type */
6986 fprintf(outfile,"CAST (%p) from type (",tree);
6987 printTypeChain(tree->right->ftype,outfile);
6988 fprintf(outfile,") to type (");
6989 printTypeChain(tree->ftype,outfile);
6990 fprintf(outfile,")\n");
6991 ast_print(tree->right,outfile,indent+2);
6995 fprintf(outfile,"ANDAND (%p) type (",tree);
6996 printTypeChain(tree->ftype,outfile);
6997 fprintf(outfile,")\n");
6998 ast_print(tree->left,outfile,indent+2);
6999 ast_print(tree->right,outfile,indent+2);
7002 fprintf(outfile,"OROR (%p) type (",tree);
7003 printTypeChain(tree->ftype,outfile);
7004 fprintf(outfile,")\n");
7005 ast_print(tree->left,outfile,indent+2);
7006 ast_print(tree->right,outfile,indent+2);
7009 /*------------------------------------------------------------------*/
7010 /*----------------------------*/
7011 /* comparison operators */
7012 /*----------------------------*/
7014 fprintf(outfile,"GT(>) (%p) type (",tree);
7015 printTypeChain(tree->ftype,outfile);
7016 fprintf(outfile,")\n");
7017 ast_print(tree->left,outfile,indent+2);
7018 ast_print(tree->right,outfile,indent+2);
7021 fprintf(outfile,"LT(<) (%p) type (",tree);
7022 printTypeChain(tree->ftype,outfile);
7023 fprintf(outfile,")\n");
7024 ast_print(tree->left,outfile,indent+2);
7025 ast_print(tree->right,outfile,indent+2);
7028 fprintf(outfile,"LE(<=) (%p) type (",tree);
7029 printTypeChain(tree->ftype,outfile);
7030 fprintf(outfile,")\n");
7031 ast_print(tree->left,outfile,indent+2);
7032 ast_print(tree->right,outfile,indent+2);
7035 fprintf(outfile,"GE(>=) (%p) type (",tree);
7036 printTypeChain(tree->ftype,outfile);
7037 fprintf(outfile,")\n");
7038 ast_print(tree->left,outfile,indent+2);
7039 ast_print(tree->right,outfile,indent+2);
7042 fprintf(outfile,"EQ(==) (%p) type (",tree);
7043 printTypeChain(tree->ftype,outfile);
7044 fprintf(outfile,")\n");
7045 ast_print(tree->left,outfile,indent+2);
7046 ast_print(tree->right,outfile,indent+2);
7049 fprintf(outfile,"NE(!=) (%p) type (",tree);
7050 printTypeChain(tree->ftype,outfile);
7051 fprintf(outfile,")\n");
7052 ast_print(tree->left,outfile,indent+2);
7053 ast_print(tree->right,outfile,indent+2);
7054 /*------------------------------------------------------------------*/
7055 /*----------------------------*/
7057 /*----------------------------*/
7058 case SIZEOF: /* evaluate wihout code generation */
7059 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7062 /*------------------------------------------------------------------*/
7063 /*----------------------------*/
7064 /* conditional operator '?' */
7065 /*----------------------------*/
7067 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7068 printTypeChain(tree->ftype,outfile);
7069 fprintf(outfile,")\n");
7070 ast_print(tree->left,outfile,indent+2);
7071 ast_print(tree->right,outfile,indent+2);
7075 fprintf(outfile,"COLON(:) (%p) type (",tree);
7076 printTypeChain(tree->ftype,outfile);
7077 fprintf(outfile,")\n");
7078 ast_print(tree->left,outfile,indent+2);
7079 ast_print(tree->right,outfile,indent+2);
7082 /*------------------------------------------------------------------*/
7083 /*----------------------------*/
7084 /* assignment operators */
7085 /*----------------------------*/
7087 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7088 printTypeChain(tree->ftype,outfile);
7089 fprintf(outfile,")\n");
7090 ast_print(tree->left,outfile,indent+2);
7091 ast_print(tree->right,outfile,indent+2);
7094 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7095 printTypeChain(tree->ftype,outfile);
7096 fprintf(outfile,")\n");
7097 ast_print(tree->left,outfile,indent+2);
7098 ast_print(tree->right,outfile,indent+2);
7101 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7102 printTypeChain(tree->ftype,outfile);
7103 fprintf(outfile,")\n");
7104 ast_print(tree->left,outfile,indent+2);
7105 ast_print(tree->right,outfile,indent+2);
7108 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7109 printTypeChain(tree->ftype,outfile);
7110 fprintf(outfile,")\n");
7111 ast_print(tree->left,outfile,indent+2);
7112 ast_print(tree->right,outfile,indent+2);
7115 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7116 printTypeChain(tree->ftype,outfile);
7117 fprintf(outfile,")\n");
7118 ast_print(tree->left,outfile,indent+2);
7119 ast_print(tree->right,outfile,indent+2);
7122 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7123 printTypeChain(tree->ftype,outfile);
7124 fprintf(outfile,")\n");
7125 ast_print(tree->left,outfile,indent+2);
7126 ast_print(tree->right,outfile,indent+2);
7129 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7130 printTypeChain(tree->ftype,outfile);
7131 fprintf(outfile,")\n");
7132 ast_print(tree->left,outfile,indent+2);
7133 ast_print(tree->right,outfile,indent+2);
7135 /*------------------------------------------------------------------*/
7136 /*----------------------------*/
7138 /*----------------------------*/
7140 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7141 printTypeChain(tree->ftype,outfile);
7142 fprintf(outfile,")\n");
7143 ast_print(tree->left,outfile,indent+2);
7144 ast_print(tree->right,outfile,indent+2);
7146 /*------------------------------------------------------------------*/
7147 /*----------------------------*/
7149 /*----------------------------*/
7151 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7152 printTypeChain(tree->ftype,outfile);
7153 fprintf(outfile,")\n");
7154 ast_print(tree->left,outfile,indent+2);
7155 ast_print(tree->right,outfile,indent+2);
7157 /*------------------------------------------------------------------*/
7158 /*----------------------------*/
7159 /* straight assignemnt */
7160 /*----------------------------*/
7162 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7163 printTypeChain(tree->ftype,outfile);
7164 fprintf(outfile,")\n");
7165 ast_print(tree->left,outfile,indent+2);
7166 ast_print(tree->right,outfile,indent+2);
7168 /*------------------------------------------------------------------*/
7169 /*----------------------------*/
7170 /* comma operator */
7171 /*----------------------------*/
7173 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7174 printTypeChain(tree->ftype,outfile);
7175 fprintf(outfile,")\n");
7176 ast_print(tree->left,outfile,indent+2);
7177 ast_print(tree->right,outfile,indent+2);
7179 /*------------------------------------------------------------------*/
7180 /*----------------------------*/
7182 /*----------------------------*/
7185 fprintf(outfile,"CALL (%p) type (",tree);
7186 printTypeChain(tree->ftype,outfile);
7187 fprintf(outfile,")\n");
7188 ast_print(tree->left,outfile,indent+2);
7189 ast_print(tree->right,outfile,indent+2);
7192 fprintf(outfile,"PARMS\n");
7193 ast_print(tree->left,outfile,indent+2);
7194 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7195 ast_print(tree->right,outfile,indent+2);
7198 /*------------------------------------------------------------------*/
7199 /*----------------------------*/
7200 /* return statement */
7201 /*----------------------------*/
7203 fprintf(outfile,"RETURN (%p) type (",tree);
7205 printTypeChain(tree->right->ftype,outfile);
7207 fprintf(outfile,")\n");
7208 ast_print(tree->right,outfile,indent+2);
7210 /*------------------------------------------------------------------*/
7211 /*----------------------------*/
7212 /* label statement */
7213 /*----------------------------*/
7215 fprintf(outfile,"LABEL (%p)\n",tree);
7216 ast_print(tree->left,outfile,indent+2);
7217 ast_print(tree->right,outfile,indent);
7219 /*------------------------------------------------------------------*/
7220 /*----------------------------*/
7221 /* switch statement */
7222 /*----------------------------*/
7226 fprintf(outfile,"SWITCH (%p) ",tree);
7227 ast_print(tree->left,outfile,0);
7228 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7229 INDENT(indent+2,outfile);
7230 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7231 (int) ulFromVal(val),
7232 tree->values.switchVals.swNum,
7233 (int) ulFromVal(val));
7235 ast_print(tree->right,outfile,indent);
7238 /*------------------------------------------------------------------*/
7239 /*----------------------------*/
7241 /*----------------------------*/
7243 fprintf(outfile,"IF (%p) \n",tree);
7244 ast_print(tree->left,outfile,indent+2);
7245 if (tree->trueLabel) {
7246 INDENT(indent+2,outfile);
7247 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7249 if (tree->falseLabel) {
7250 INDENT(indent+2,outfile);
7251 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7253 ast_print(tree->right,outfile,indent+2);
7255 /*----------------------------*/
7256 /* goto Statement */
7257 /*----------------------------*/
7259 fprintf(outfile,"GOTO (%p) \n",tree);
7260 ast_print(tree->left,outfile,indent+2);
7261 fprintf(outfile,"\n");
7263 /*------------------------------------------------------------------*/
7264 /*----------------------------*/
7266 /*----------------------------*/
7268 fprintf(outfile,"FOR (%p) \n",tree);
7269 if (AST_FOR( tree, initExpr)) {
7270 INDENT(indent+2,outfile);
7271 fprintf(outfile,"INIT EXPR ");
7272 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7274 if (AST_FOR( tree, condExpr)) {
7275 INDENT(indent+2,outfile);
7276 fprintf(outfile,"COND EXPR ");
7277 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7279 if (AST_FOR( tree, loopExpr)) {
7280 INDENT(indent+2,outfile);
7281 fprintf(outfile,"LOOP EXPR ");
7282 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7284 fprintf(outfile,"FOR LOOP BODY \n");
7285 ast_print(tree->left,outfile,indent+2);
7288 fprintf(outfile,"CRITICAL (%p) \n",tree);
7289 ast_print(tree->left,outfile,indent+2);
7297 ast_print(t,stdout,0);
7300 /*-----------------------------------------------------------------*/
7301 /* astErrors : returns non-zero if errors present in tree */
7302 /*-----------------------------------------------------------------*/
7303 int astErrors(ast *t)
7312 if (t->type == EX_VALUE
7313 && t->opval.val->sym
7314 && t->opval.val->sym->undefined)
7317 errors += astErrors(t->left);
7318 errors += astErrors(t->right);