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 if (IS_CAST_OP (*actParm)
858 || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
860 /* Parameter was explicitly typecast; don't touch it. */
864 ftype = (*actParm)->ftype;
866 /* If it's a char, upcast to int. */
867 if (IS_INTEGRAL (ftype)
868 && (getSize (ftype) < (unsigned) INTSIZE))
870 newType = newAst_LINK(INTTYPE);
873 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
875 newType = newAst_LINK (copyLinkChain(ftype));
876 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
879 if (IS_AGGREGATE (ftype))
881 newType = newAst_LINK (copyLinkChain (ftype));
882 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887 /* cast required; change this op to a cast. */
888 (*actParm)->decorated = 0;
889 *actParm = newNode (CAST, newType, *actParm);
890 (*actParm)->filename = (*actParm)->right->filename;
891 (*actParm)->lineno = (*actParm)->right->lineno;
893 decorateType (*actParm, RESULT_TYPE_NONE);
898 /* if defined parameters ended but actual has not & */
900 if (!defParm && *actParm &&
901 (options.stackAuto || IFFUNC_ISREENT (functype)))
904 resolveSymbols (*actParm);
906 /* the parameter type must be at least castable */
907 if (compareType (defParm->type, (*actParm)->ftype) == 0)
909 werror (E_INCOMPAT_TYPES);
910 printFromToType ((*actParm)->ftype, defParm->type);
914 /* if the parameter is castable then add the cast */
915 if (compareType (defParm->type, (*actParm)->ftype) < 0)
919 resultType = getResultTypeFromType (defParm->etype);
920 pTree = resolveSymbols (copyAst (*actParm));
922 /* now change the current one to a cast */
923 (*actParm)->type = EX_OP;
924 (*actParm)->opval.op = CAST;
925 (*actParm)->left = newAst_LINK (defParm->type);
926 (*actParm)->right = pTree;
927 (*actParm)->decorated = 0; /* force typechecking */
928 decorateType (*actParm, resultType);
931 /* make a copy and change the regparm type to the defined parm */
932 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
933 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
934 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
936 /* if the function is being called via a pointer & */
937 /* this parameter is not passed in registers */
938 /* then the function must be defined reentrant */
939 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
940 !IFFUNC_ISREENT (functype) && !options.stackAuto)
942 werror (E_NONRENT_ARGS);
951 /*-----------------------------------------------------------------*/
952 /* createIvalType - generates ival for basic types */
953 /*-----------------------------------------------------------------*/
955 createIvalType (ast * sym, sym_link * type, initList * ilist)
959 /* if initList is deep */
960 if (ilist->type == INIT_DEEP)
961 ilist = ilist->init.deep;
963 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
964 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
967 /*-----------------------------------------------------------------*/
968 /* createIvalStruct - generates initial value for structures */
969 /*-----------------------------------------------------------------*/
971 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
978 sflds = SPEC_STRUCT (type)->fields;
979 if (ilist->type != INIT_DEEP)
981 werror (E_INIT_STRUCT, "");
985 iloop = ilist->init.deep;
987 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
989 /* if we have come to end */
993 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
994 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
995 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
996 iloop, rast, rootValue)),
1003 if (IS_AST_VALUE (sym))
1004 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1005 W_EXCESS_INITIALIZERS, "struct",
1006 sym->opval.val->sym->name);
1008 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1015 /*-----------------------------------------------------------------*/
1016 /* createIvalArray - generates code for array initialization */
1017 /*-----------------------------------------------------------------*/
1019 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1023 int lcnt = 0, size = 0;
1024 literalList *literalL;
1026 /* take care of the special case */
1027 /* array of characters can be init */
1029 if (IS_CHAR (type->next))
1030 if ((rast = createIvalCharPtr (sym,
1032 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1035 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1037 /* not the special case */
1038 if (ilist->type != INIT_DEEP)
1040 werror (E_INIT_STRUCT, "");
1044 iloop = ilist->init.deep;
1045 lcnt = DCL_ELEM (type);
1047 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1051 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1053 rast = newNode(ARRAYINIT, aSym, NULL);
1054 rast->values.constlist = literalL;
1056 // Make sure size is set to length of initializer list.
1060 iloop = iloop->next;
1063 if (lcnt && size > lcnt)
1065 // Array size was specified, and we have more initializers than needed.
1066 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1067 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1076 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1077 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1078 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1079 iloop = (iloop ? iloop->next : NULL);
1085 /* no of elements given and we */
1086 /* have generated for all of them */
1089 // is this a better way? at least it won't crash
1090 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1091 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1098 /* if we have not been given a size */
1099 if (!DCL_ELEM (type))
1101 /* check, if it's a flexible array */
1102 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1103 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1105 DCL_ELEM (type) = size;
1108 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1112 /*-----------------------------------------------------------------*/
1113 /* createIvalCharPtr - generates initial values for char pointers */
1114 /*-----------------------------------------------------------------*/
1116 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1121 /* if this is a pointer & right is a literal array then */
1122 /* just assignment will do */
1123 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1124 SPEC_SCLS (iexpr->etype) == S_CODE)
1125 && IS_ARRAY (iexpr->ftype)))
1126 return newNode ('=', sym, iexpr);
1128 /* left side is an array so we have to assign each element */
1129 if ((IS_LITERAL (iexpr->etype) ||
1130 SPEC_SCLS (iexpr->etype) == S_CODE)
1131 && IS_ARRAY (iexpr->ftype))
1133 /* for each character generate an assignment */
1134 /* to the array element */
1135 char *s = SPEC_CVAL (iexpr->etype).v_char;
1137 unsigned int symsize = getSize (type);
1139 size = getSize (iexpr->ftype);
1140 if (symsize && size>symsize)
1142 if (size>(symsize+1))
1144 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1146 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1152 for (i=0;i<size;i++)
1154 rast = newNode (NULLOP,
1158 newAst_VALUE (valueFromLit ((float) i))),
1159 newAst_VALUE (valueFromLit (*s))));
1163 // now WE don't need iexpr's symbol anymore
1164 freeStringSymbol(AST_SYMBOL(iexpr));
1166 /* if we have not been given a size */
1167 if (!DCL_ELEM (type))
1169 /* check, if it's a flexible array */
1170 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1171 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1173 DCL_ELEM (type) = size;
1176 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1182 /*-----------------------------------------------------------------*/
1183 /* createIvalPtr - generates initial value for pointers */
1184 /*-----------------------------------------------------------------*/
1186 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1192 if (ilist->type == INIT_DEEP)
1193 ilist = ilist->init.deep;
1195 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1197 /* if character pointer */
1198 if (IS_CHAR (type->next))
1199 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1202 return newNode ('=', sym, iexpr);
1205 /*-----------------------------------------------------------------*/
1206 /* createIval - generates code for initial value */
1207 /*-----------------------------------------------------------------*/
1209 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1216 /* if structure then */
1217 if (IS_STRUCT (type))
1218 rast = createIvalStruct (sym, type, ilist, rootValue);
1220 /* if this is a pointer */
1222 rast = createIvalPtr (sym, type, ilist, rootValue);
1224 /* if this is an array */
1225 if (IS_ARRAY (type))
1226 rast = createIvalArray (sym, type, ilist, rootValue);
1228 /* if type is SPECIFIER */
1230 rast = createIvalType (sym, type, ilist);
1233 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1235 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1238 /*-----------------------------------------------------------------*/
1239 /* initAggregates - initialises aggregate variables with initv */
1240 /*-----------------------------------------------------------------*/
1241 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1242 ast *newAst = newAst_VALUE (symbolVal (sym));
1243 return createIval (newAst, sym->type, ival, wid, newAst);
1246 /*-----------------------------------------------------------------*/
1247 /* gatherAutoInit - creates assignment expressions for initial */
1249 /*-----------------------------------------------------------------*/
1251 gatherAutoInit (symbol * autoChain)
1258 for (sym = autoChain; sym; sym = sym->next)
1261 /* resolve the symbols in the ival */
1263 resolveIvalSym (sym->ival, sym->type);
1266 /* if we are PIC16 port,
1267 * and this is a static,
1268 * and have initial value,
1269 * and not S_CODE, don't emit in gs segment,
1270 * but allow glue.c:pic16emitRegularMap to put symbol
1271 * in idata section */
1272 if(TARGET_IS_PIC16 &&
1273 IS_STATIC (sym->etype) && sym->ival
1274 && SPEC_SCLS(sym->etype) != S_CODE) {
1275 SPEC_SCLS (sym->etype) = S_DATA;
1280 /* if this is a static variable & has an */
1281 /* initial value the code needs to be lifted */
1282 /* here to the main portion since they can be */
1283 /* initialised only once at the start */
1284 if (IS_STATIC (sym->etype) && sym->ival &&
1285 SPEC_SCLS (sym->etype) != S_CODE)
1289 /* insert the symbol into the symbol table */
1290 /* with level = 0 & name = rname */
1291 newSym = copySymbol (sym);
1292 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1294 /* now lift the code to main */
1295 if (IS_AGGREGATE (sym->type)) {
1296 work = initAggregates (sym, sym->ival, NULL);
1298 if (getNelements(sym->type, sym->ival)>1) {
1299 werrorfl (sym->fileDef, sym->lineDef,
1300 W_EXCESS_INITIALIZERS, "scalar",
1303 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1304 list2expr (sym->ival));
1307 setAstFileLine (work, sym->fileDef, sym->lineDef);
1311 staticAutos = newNode (NULLOP, staticAutos, work);
1318 /* if there is an initial value */
1319 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1321 initList *ilist=sym->ival;
1323 while (ilist->type == INIT_DEEP) {
1324 ilist = ilist->init.deep;
1327 /* update lineno for error msg */
1328 filename = sym->fileDef;
1329 lineno = sym->lineDef;
1330 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1332 if (IS_AGGREGATE (sym->type)) {
1333 work = initAggregates (sym, sym->ival, NULL);
1335 if (getNelements(sym->type, sym->ival)>1) {
1336 werrorfl (sym->fileDef, sym->lineDef,
1337 W_EXCESS_INITIALIZERS, "scalar",
1340 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1341 list2expr (sym->ival));
1345 setAstFileLine (work, sym->fileDef, sym->lineDef);
1349 init = newNode (NULLOP, init, work);
1358 /*-----------------------------------------------------------------*/
1359 /* freeStringSymbol - delete a literal string if no more usage */
1360 /*-----------------------------------------------------------------*/
1361 void freeStringSymbol(symbol *sym) {
1362 /* make sure this is a literal string */
1363 assert (sym->isstrlit);
1364 if (--sym->isstrlit == 0) { // lower the usage count
1365 memmap *segment=SPEC_OCLS(sym->etype);
1367 deleteSetItem(&segment->syms, sym);
1372 /*-----------------------------------------------------------------*/
1373 /* stringToSymbol - creates a symbol from a literal string */
1374 /*-----------------------------------------------------------------*/
1376 stringToSymbol (value * val)
1378 char name[SDCC_NAME_MAX + 1];
1379 static int charLbl = 0;
1384 // have we heard this before?
1385 for (sp = statsg->syms; sp; sp = sp->next)
1388 size = getSize (sym->type);
1389 if (sym->isstrlit && size == getSize (val->type) &&
1390 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1392 // yes, this is old news. Don't publish it again.
1393 sym->isstrlit++; // but raise the usage count
1394 return symbolVal (sym);
1398 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1399 sym = newSymbol (name, 0); /* make it @ level 0 */
1400 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1402 /* copy the type from the value passed */
1403 sym->type = copyLinkChain (val->type);
1404 sym->etype = getSpec (sym->type);
1405 /* change to storage class & output class */
1406 SPEC_SCLS (sym->etype) = S_CODE;
1407 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1408 SPEC_STAT (sym->etype) = 1;
1409 /* make the level & block = 0 */
1410 sym->block = sym->level = 0;
1412 /* create an ival */
1413 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1418 allocVariables (sym);
1421 return symbolVal (sym);
1425 /*-----------------------------------------------------------------*/
1426 /* processBlockVars - will go thru the ast looking for block if */
1427 /* a block is found then will allocate the syms */
1428 /* will also gather the auto inits present */
1429 /*-----------------------------------------------------------------*/
1431 processBlockVars (ast * tree, int *stack, int action)
1436 /* if this is a block */
1437 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1441 if (action == ALLOCATE)
1443 *stack += allocVariables (tree->values.sym);
1444 autoInit = gatherAutoInit (tree->values.sym);
1446 /* if there are auto inits then do them */
1448 tree->left = newNode (NULLOP, autoInit, tree->left);
1450 else /* action is deallocate */
1451 deallocLocal (tree->values.sym);
1454 processBlockVars (tree->left, stack, action);
1455 processBlockVars (tree->right, stack, action);
1460 /*-------------------------------------------------------------*/
1461 /* constExprTree - returns TRUE if this tree is a constant */
1463 /*-------------------------------------------------------------*/
1464 bool constExprTree (ast *cexpr) {
1470 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1472 switch (cexpr->type)
1475 if (IS_AST_LIT_VALUE(cexpr)) {
1476 // this is a literal
1479 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1480 // a function's address will never change
1483 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1484 // an array's address will never change
1487 if (IS_AST_SYM_VALUE(cexpr) &&
1488 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1489 // a symbol in code space will never change
1490 // This is only for the 'char *s="hallo"' case and will have to leave
1491 //printf(" code space symbol");
1496 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1497 "unexpected link in expression tree\n");
1500 if (cexpr->opval.op==ARRAYINIT) {
1501 // this is a list of literals
1504 if (cexpr->opval.op=='=') {
1505 return constExprTree(cexpr->right);
1507 if (cexpr->opval.op==CAST) {
1508 // cast ignored, maybe we should throw a warning here?
1509 return constExprTree(cexpr->right);
1511 if (cexpr->opval.op=='&') {
1514 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1517 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1522 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1527 /*-----------------------------------------------------------------*/
1528 /* constExprValue - returns the value of a constant expression */
1529 /* or NULL if it is not a constant expression */
1530 /*-----------------------------------------------------------------*/
1532 constExprValue (ast * cexpr, int check)
1534 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1536 /* if this is not a constant then */
1537 if (!IS_LITERAL (cexpr->ftype))
1539 /* then check if this is a literal array
1541 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1542 SPEC_CVAL (cexpr->etype).v_char &&
1543 IS_ARRAY (cexpr->ftype))
1545 value *val = valFromType (cexpr->ftype);
1546 SPEC_SCLS (val->etype) = S_LITERAL;
1547 val->sym = cexpr->opval.val->sym;
1548 val->sym->type = copyLinkChain (cexpr->ftype);
1549 val->sym->etype = getSpec (val->sym->type);
1550 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1554 /* if we are casting a literal value then */
1555 if (IS_AST_OP (cexpr) &&
1556 cexpr->opval.op == CAST &&
1557 IS_LITERAL (cexpr->right->ftype))
1559 return valCastLiteral (cexpr->ftype,
1560 floatFromVal (cexpr->right->opval.val));
1563 if (IS_AST_VALUE (cexpr))
1565 return cexpr->opval.val;
1569 werror (E_CONST_EXPECTED, "found expression");
1574 /* return the value */
1575 if (IS_AST_VALUE (cexpr))
1577 return cexpr->opval.val;
1582 /*-----------------------------------------------------------------*/
1583 /* isLabelInAst - will return true if a given label is found */
1584 /*-----------------------------------------------------------------*/
1586 isLabelInAst (symbol * label, ast * tree)
1588 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1591 if (IS_AST_OP (tree) &&
1592 tree->opval.op == LABEL &&
1593 isSymbolEqual (AST_SYMBOL (tree->left), label))
1596 return isLabelInAst (label, tree->right) &&
1597 isLabelInAst (label, tree->left);
1600 /*-----------------------------------------------------------------*/
1601 /* isLoopCountable - return true if the loop count can be determi- */
1602 /* -ned at compile time . */
1603 /*-----------------------------------------------------------------*/
1605 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1606 symbol ** sym, ast ** init, ast ** end)
1609 /* the loop is considered countable if the following
1610 conditions are true :-
1612 a) initExpr :- <sym> = <const>
1613 b) condExpr :- <sym> < <const1>
1614 c) loopExpr :- <sym> ++
1617 /* first check the initExpr */
1618 if (IS_AST_OP (initExpr) &&
1619 initExpr->opval.op == '=' && /* is assignment */
1620 IS_AST_SYM_VALUE (initExpr->left))
1621 { /* left is a symbol */
1623 *sym = AST_SYMBOL (initExpr->left);
1624 *init = initExpr->right;
1629 /* don't reverse loop with volatile counter */
1630 if (IS_VOLATILE ((*sym)->type))
1633 /* for now the symbol has to be of
1635 if (!IS_INTEGRAL ((*sym)->type))
1638 /* now check condExpr */
1639 if (IS_AST_OP (condExpr))
1642 switch (condExpr->opval.op)
1645 if (IS_AST_SYM_VALUE (condExpr->left) &&
1646 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1647 IS_AST_LIT_VALUE (condExpr->right))
1649 *end = condExpr->right;
1655 if (IS_AST_OP (condExpr->left) &&
1656 condExpr->left->opval.op == '>' &&
1657 IS_AST_LIT_VALUE (condExpr->left->right) &&
1658 IS_AST_SYM_VALUE (condExpr->left->left) &&
1659 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1662 *end = newNode ('+', condExpr->left->right,
1663 newAst_VALUE (constCharVal (1)));
1676 /* check loop expression is of the form <sym>++ */
1677 if (!IS_AST_OP (loopExpr))
1680 /* check if <sym> ++ */
1681 if (loopExpr->opval.op == INC_OP)
1687 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1688 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1695 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1696 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1704 if (loopExpr->opval.op == ADD_ASSIGN)
1707 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1708 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1709 IS_AST_LIT_VALUE (loopExpr->right) &&
1710 AST_ULONG_VALUE (loopExpr->right) != 1)
1718 /*-----------------------------------------------------------------*/
1719 /* astHasVolatile - returns true if ast contains any volatile */
1720 /*-----------------------------------------------------------------*/
1722 astHasVolatile (ast * tree)
1727 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1730 if (IS_AST_OP (tree))
1731 return astHasVolatile (tree->left) ||
1732 astHasVolatile (tree->right);
1737 /*-----------------------------------------------------------------*/
1738 /* astHasPointer - return true if the ast contains any ptr variable */
1739 /*-----------------------------------------------------------------*/
1741 astHasPointer (ast * tree)
1746 if (IS_AST_LINK (tree))
1749 /* if we hit an array expression then check
1750 only the left side */
1751 if (IS_AST_OP (tree) && tree->opval.op == '[')
1752 return astHasPointer (tree->left);
1754 if (IS_AST_VALUE (tree))
1755 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1757 return astHasPointer (tree->left) ||
1758 astHasPointer (tree->right);
1762 /*-----------------------------------------------------------------*/
1763 /* astHasSymbol - return true if the ast has the given symbol */
1764 /*-----------------------------------------------------------------*/
1766 astHasSymbol (ast * tree, symbol * sym)
1768 if (!tree || IS_AST_LINK (tree))
1771 if (IS_AST_VALUE (tree))
1773 if (IS_AST_SYM_VALUE (tree))
1774 return isSymbolEqual (AST_SYMBOL (tree), sym);
1779 return astHasSymbol (tree->left, sym) ||
1780 astHasSymbol (tree->right, sym);
1783 /*-----------------------------------------------------------------*/
1784 /* astHasDeref - return true if the ast has an indirect access */
1785 /*-----------------------------------------------------------------*/
1787 astHasDeref (ast * tree)
1789 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1792 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1794 return astHasDeref (tree->left) || astHasDeref (tree->right);
1797 /*-----------------------------------------------------------------*/
1798 /* isConformingBody - the loop body has to conform to a set of rules */
1799 /* for the loop to be considered reversible read on for rules */
1800 /*-----------------------------------------------------------------*/
1802 isConformingBody (ast * pbody, symbol * sym, ast * body)
1805 /* we are going to do a pre-order traversal of the
1806 tree && check for the following conditions. (essentially
1807 a set of very shallow tests )
1808 a) the sym passed does not participate in
1809 any arithmetic operation
1810 b) There are no function calls
1811 c) all jumps are within the body
1812 d) address of loop control variable not taken
1813 e) if an assignment has a pointer on the
1814 left hand side make sure right does not have
1815 loop control variable */
1817 /* if we reach the end or a leaf then true */
1818 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1821 /* if anything else is "volatile" */
1822 if (IS_VOLATILE (TETYPE (pbody)))
1825 /* we will walk the body in a pre-order traversal for
1827 switch (pbody->opval.op)
1829 /*------------------------------------------------------------------*/
1831 // if the loopvar is used as an index
1832 /* array op is commutative -- must check both left & right */
1833 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1836 return isConformingBody (pbody->right, sym, body)
1837 && isConformingBody (pbody->left, sym, body);
1839 /*------------------------------------------------------------------*/
1844 /*------------------------------------------------------------------*/
1848 /* sure we are not sym is not modified */
1850 IS_AST_SYM_VALUE (pbody->left) &&
1851 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1855 IS_AST_SYM_VALUE (pbody->right) &&
1856 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1861 /*------------------------------------------------------------------*/
1863 case '*': /* can be unary : if right is null then unary operation */
1868 /* if right is NULL then unary operation */
1869 /*------------------------------------------------------------------*/
1870 /*----------------------------*/
1872 /*----------------------------*/
1875 if (IS_AST_SYM_VALUE (pbody->left) &&
1876 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1879 return isConformingBody (pbody->left, sym, body);
1883 if (astHasSymbol (pbody->left, sym) ||
1884 astHasSymbol (pbody->right, sym))
1889 /*------------------------------------------------------------------*/
1900 if (IS_AST_SYM_VALUE (pbody->left) &&
1901 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1904 if (IS_AST_SYM_VALUE (pbody->right) &&
1905 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1908 return isConformingBody (pbody->left, sym, body) &&
1909 isConformingBody (pbody->right, sym, body);
1917 if (IS_AST_SYM_VALUE (pbody->left) &&
1918 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1920 return isConformingBody (pbody->left, sym, body);
1922 /*------------------------------------------------------------------*/
1934 case SIZEOF: /* evaluate wihout code generation */
1936 if (IS_AST_SYM_VALUE (pbody->left) &&
1937 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1940 if (IS_AST_SYM_VALUE (pbody->right) &&
1941 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1944 return isConformingBody (pbody->left, sym, body) &&
1945 isConformingBody (pbody->right, sym, body);
1947 /*------------------------------------------------------------------*/
1950 /* if left has a pointer & right has loop
1951 control variable then we cannot */
1952 if (astHasPointer (pbody->left) &&
1953 astHasSymbol (pbody->right, sym))
1955 if (astHasVolatile (pbody->left))
1958 if (IS_AST_SYM_VALUE (pbody->left)) {
1959 // if the loopvar has an assignment
1960 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1962 // if the loopvar is used in another (maybe conditional) block
1963 if (astHasSymbol (pbody->right, sym) &&
1964 (pbody->level >= body->level)) {
1969 if (astHasVolatile (pbody->left))
1972 if (astHasDeref(pbody->right)) return FALSE;
1974 return isConformingBody (pbody->left, sym, body) &&
1975 isConformingBody (pbody->right, sym, body);
1986 assert ("Parser should not have generated this\n");
1988 /*------------------------------------------------------------------*/
1989 /*----------------------------*/
1990 /* comma operator */
1991 /*----------------------------*/
1993 return isConformingBody (pbody->left, sym, body) &&
1994 isConformingBody (pbody->right, sym, body);
1996 /*------------------------------------------------------------------*/
1997 /*----------------------------*/
1999 /*----------------------------*/
2001 /* if local & not passed as paramater then ok */
2002 if (sym->level && !astHasSymbol(pbody->right,sym))
2006 /*------------------------------------------------------------------*/
2007 /*----------------------------*/
2008 /* return statement */
2009 /*----------------------------*/
2014 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2019 if (astHasSymbol (pbody->left, sym))
2026 return isConformingBody (pbody->left, sym, body) &&
2027 isConformingBody (pbody->right, sym, body);
2033 /*-----------------------------------------------------------------*/
2034 /* isLoopReversible - takes a for loop as input && returns true */
2035 /* if the for loop is reversible. If yes will set the value of */
2036 /* the loop control var & init value & termination value */
2037 /*-----------------------------------------------------------------*/
2039 isLoopReversible (ast * loop, symbol ** loopCntrl,
2040 ast ** init, ast ** end)
2042 /* if option says don't do it then don't */
2043 if (optimize.noLoopReverse)
2045 /* there are several tests to determine this */
2047 /* for loop has to be of the form
2048 for ( <sym> = <const1> ;
2049 [<sym> < <const2>] ;
2050 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2052 if (!isLoopCountable (AST_FOR (loop, initExpr),
2053 AST_FOR (loop, condExpr),
2054 AST_FOR (loop, loopExpr),
2055 loopCntrl, init, end))
2058 /* now do some serious checking on the body of the loop
2061 return isConformingBody (loop->left, *loopCntrl, loop->left);
2065 /*-----------------------------------------------------------------*/
2066 /* replLoopSym - replace the loop sym by loop sym -1 */
2067 /*-----------------------------------------------------------------*/
2069 replLoopSym (ast * body, symbol * sym)
2072 if (!body || IS_AST_LINK (body))
2075 if (IS_AST_SYM_VALUE (body))
2078 if (isSymbolEqual (AST_SYMBOL (body), sym))
2082 body->opval.op = '-';
2083 body->left = newAst_VALUE (symbolVal (sym));
2084 body->right = newAst_VALUE (constCharVal (1));
2092 replLoopSym (body->left, sym);
2093 replLoopSym (body->right, sym);
2097 /*-----------------------------------------------------------------*/
2098 /* reverseLoop - do the actual loop reversal */
2099 /*-----------------------------------------------------------------*/
2101 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2105 /* create the following tree
2110 if (sym) goto for_continue ;
2113 /* put it together piece by piece */
2114 rloop = newNode (NULLOP,
2115 createIf (newAst_VALUE (symbolVal (sym)),
2117 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2120 newAst_VALUE (symbolVal (sym)),
2123 replLoopSym (loop->left, sym);
2124 setAstFileLine (rloop, init->filename, init->lineno);
2126 rloop = newNode (NULLOP,
2128 newAst_VALUE (symbolVal (sym)),
2129 newNode ('-', end, init)),
2130 createLabel (AST_FOR (loop, continueLabel),
2134 newNode (SUB_ASSIGN,
2135 newAst_VALUE (symbolVal (sym)),
2136 newAst_VALUE (constCharVal (1))),
2139 rloop->lineno=init->lineno;
2140 return decorateType (rloop, RESULT_TYPE_NONE);
2144 /*-----------------------------------------------------------------*/
2145 /* searchLitOp - search tree (*ops only) for an ast with literal */
2146 /*-----------------------------------------------------------------*/
2148 searchLitOp (ast *tree, ast **parent, const char *ops)
2152 if (tree && optimize.global_cse)
2154 /* is there a literal operand? */
2156 IS_AST_OP(tree->right) &&
2157 tree->right->right &&
2158 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2160 if (IS_LITERAL (RTYPE (tree->right)) !=
2161 IS_LITERAL (LTYPE (tree->right)))
2163 tree->right->decorated = 0;
2164 tree->decorated = 0;
2168 ret = searchLitOp (tree->right, parent, ops);
2173 IS_AST_OP(tree->left) &&
2174 tree->left->right &&
2175 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2177 if (IS_LITERAL (RTYPE (tree->left)) !=
2178 IS_LITERAL (LTYPE (tree->left)))
2180 tree->left->decorated = 0;
2181 tree->decorated = 0;
2185 ret = searchLitOp (tree->left, parent, ops);
2193 /*-----------------------------------------------------------------*/
2194 /* getResultFromType */
2195 /*-----------------------------------------------------------------*/
2197 getResultTypeFromType (sym_link *type)
2199 /* type = getSpec (type); */
2201 return RESULT_TYPE_BIT;
2202 if (IS_BITFIELD (type))
2204 int blen = SPEC_BLEN (type);
2207 return RESULT_TYPE_BIT;
2209 return RESULT_TYPE_CHAR;
2210 return RESULT_TYPE_INT;
2213 return RESULT_TYPE_CHAR;
2214 if (IS_INT (type) && !IS_LONG (type))
2215 return RESULT_TYPE_INT;
2216 return RESULT_TYPE_OTHER;
2219 /*-----------------------------------------------------------------*/
2220 /* addCast - adds casts to a type specified by RESULT_TYPE */
2221 /*-----------------------------------------------------------------*/
2223 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2226 bool upCasted = FALSE;
2230 case RESULT_TYPE_NONE:
2231 /* if thing smaller than int must be promoted to int */
2233 getSize (tree->etype) >= INTSIZE)
2234 /* promotion not necessary or already an int */
2236 /* char and bits: promote to int */
2237 newLink = newIntLink();
2240 case RESULT_TYPE_BIT:
2242 /* already an int */
2243 bitsForType (tree->etype) >= 16 ||
2244 /* bit to bit operation: don't promote, the code generators
2245 hopefully know everything about promotion rules */
2246 bitsForType (tree->etype) == 1)
2248 newLink = newIntLink();
2251 case RESULT_TYPE_CHAR:
2252 if (IS_CHAR (tree->etype) ||
2253 IS_FLOAT(tree->etype) ||
2254 IS_FIXED(tree->etype))
2256 newLink = newCharLink();
2258 case RESULT_TYPE_INT:
2260 if (getSize (tree->etype) > INTSIZE)
2262 /* warn ("Loosing significant digits"); */
2266 /* char: promote to int */
2268 getSize (tree->etype) >= INTSIZE)
2270 newLink = newIntLink();
2273 case RESULT_TYPE_IFX:
2274 case RESULT_TYPE_OTHER:
2276 /* return type is ifx, long, float: promote char to int */
2277 getSize (tree->etype) >= INTSIZE)
2279 newLink = newIntLink();
2285 tree->decorated = 0;
2286 tree = newNode (CAST, newAst_LINK (newLink), tree);
2287 tree->filename = tree->right->filename;
2288 tree->lineno = tree->right->lineno;
2289 /* keep unsigned type during cast to smaller type,
2290 but not when promoting from char to int */
2292 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2293 return decorateType (tree, resultType);
2296 /*-----------------------------------------------------------------*/
2297 /* resultTypePropagate - decides if resultType can be propagated */
2298 /*-----------------------------------------------------------------*/
2300 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2302 switch (tree->opval.op)
2319 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2320 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2321 return RESULT_TYPE_NONE;
2326 return RESULT_TYPE_NONE;
2330 return RESULT_TYPE_IFX;
2332 return RESULT_TYPE_NONE;
2336 /*-----------------------------------------------------------------*/
2337 /* getLeftResultType - gets type from left branch for propagation */
2338 /*-----------------------------------------------------------------*/
2340 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2342 switch (tree->opval.op)
2346 if (IS_PTR (LTYPE (tree)))
2347 return RESULT_TYPE_NONE;
2349 return getResultTypeFromType (LETYPE (tree));
2351 if (IS_PTR (currFunc->type->next))
2352 return RESULT_TYPE_NONE;
2354 return getResultTypeFromType (currFunc->type->next);
2356 if (!IS_ARRAY (LTYPE (tree)))
2358 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2359 return RESULT_TYPE_CHAR;
2366 /*------------------------------------------------------------------*/
2367 /* gatherImplicitVariables: assigns correct type information to */
2368 /* symbols and values created by replaceAstWithTemporary */
2369 /* and adds the symbols to the declarations list of the */
2370 /* innermost block that contains them */
2371 /*------------------------------------------------------------------*/
2373 gatherImplicitVariables (ast * tree, ast * block)
2378 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2380 /* keep track of containing scope */
2383 if (tree->type == EX_OP && tree->opval.op == '=' &&
2384 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2386 symbol *assignee = tree->left->opval.val->sym;
2388 /* special case for assignment to compiler-generated temporary variable:
2389 compute type of RHS, and set the symbol's type to match */
2390 if (assignee->type == NULL && assignee->infertype) {
2391 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2393 if (dtr != tree->right)
2396 assignee->type = copyLinkChain(TTYPE(dtr));
2397 assignee->etype = getSpec(assignee->type);
2398 SPEC_SCLS (assignee->etype) = S_AUTO;
2399 SPEC_OCLS (assignee->etype) = NULL;
2400 SPEC_EXTR (assignee->etype) = 0;
2401 SPEC_STAT (assignee->etype) = 0;
2402 SPEC_VOLATILE (assignee->etype) = 0;
2403 SPEC_ABSA (assignee->etype) = 0;
2405 wassertl(block != NULL, "implicit variable not contained in block");
2406 wassert(assignee->next == NULL);
2407 if (block != NULL) {
2408 symbol **decl = &(block->values.sym);
2411 wassert(*decl != assignee); /* should not already be in list */
2412 decl = &( (*decl)->next );
2419 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2420 tree->opval.val->type == NULL &&
2421 tree->opval.val->sym &&
2422 tree->opval.val->sym->infertype)
2424 /* fixup type of value for compiler-inferred temporary var */
2425 tree->opval.val->type = tree->opval.val->sym->type;
2426 tree->opval.val->etype = tree->opval.val->sym->etype;
2429 gatherImplicitVariables(tree->left, block);
2430 gatherImplicitVariables(tree->right, block);
2433 /*--------------------------------------------------------------------*/
2434 /* decorateType - compute type for this tree, also does type checking.*/
2435 /* This is done bottom up, since type has to flow upwards. */
2436 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2437 /* result is a char and the operand(s) are int's. */
2438 /* It also does constant folding, and parameter checking. */
2439 /*--------------------------------------------------------------------*/
2441 decorateType (ast * tree, RESULT_TYPE resultType)
2445 RESULT_TYPE resultTypeProp;
2450 /* if already has type then do nothing */
2451 if (tree->decorated)
2454 tree->decorated = 1;
2457 /* print the line */
2458 /* if not block & function */
2459 if (tree->type == EX_OP &&
2460 (tree->opval.op != FUNCTION &&
2461 tree->opval.op != BLOCK &&
2462 tree->opval.op != NULLOP))
2464 filename = tree->filename;
2465 lineno = tree->lineno;
2469 /* if any child is an error | this one is an error do nothing */
2470 if (tree->isError ||
2471 (tree->left && tree->left->isError) ||
2472 (tree->right && tree->right->isError))
2475 /*------------------------------------------------------------------*/
2476 /*----------------------------*/
2477 /* leaf has been reached */
2478 /*----------------------------*/
2479 filename = tree->filename;
2480 lineno = tree->lineno;
2481 /* if this is of type value */
2482 /* just get the type */
2483 if (tree->type == EX_VALUE)
2486 if (IS_LITERAL (tree->opval.val->etype))
2489 /* if this is a character array then declare it */
2490 if (IS_ARRAY (tree->opval.val->type))
2491 tree->opval.val = stringToSymbol (tree->opval.val);
2493 /* otherwise just copy the type information */
2494 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2498 if (tree->opval.val->sym)
2500 /* if the undefined flag is set then give error message */
2501 if (tree->opval.val->sym->undefined)
2503 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2505 TTYPE (tree) = TETYPE (tree) =
2506 tree->opval.val->type = tree->opval.val->sym->type =
2507 tree->opval.val->etype = tree->opval.val->sym->etype =
2508 copyLinkChain (INTTYPE);
2510 else if (tree->opval.val->sym->implicit)
2512 /* if implicit i.e. struct/union member then no type */
2513 TTYPE (tree) = TETYPE (tree) = NULL;
2517 /* copy the type from the value into the ast */
2518 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2520 /* and mark the symbol as referenced */
2521 tree->opval.val->sym->isref = 1;
2525 wassert(0); /* unreached: all values are literals or symbols */
2530 /* if type link for the case of cast */
2531 if (tree->type == EX_LINK)
2533 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2541 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2543 if (tree->left && tree->left->type == EX_OPERAND
2544 && (tree->left->opval.op == INC_OP
2545 || tree->left->opval.op == DEC_OP)
2546 && tree->left->left)
2548 tree->left->right = tree->left->left;
2549 tree->left->left = NULL;
2551 if (tree->right && tree->right->type == EX_OPERAND
2552 && (tree->right->opval.op == INC_OP
2553 || tree->right->opval.op == DEC_OP)
2554 && tree->right->left)
2556 tree->right->right = tree->right->left;
2557 tree->right->left = NULL;
2562 /* Before decorating the left branch we've to decide in dependence
2563 upon tree->opval.op, if resultType can be propagated */
2564 resultTypeProp = resultTypePropagate (tree, resultType);
2566 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2567 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2569 dtl = decorateType (tree->left, resultTypeProp);
2571 /* if an array node, we may need to swap branches */
2572 if (tree->opval.op == '[')
2574 /* determine which is the array & which the index */
2575 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2576 IS_INTEGRAL (LTYPE (tree)))
2578 ast *tempTree = tree->left;
2579 tree->left = tree->right;
2580 tree->right = tempTree;
2584 /* After decorating the left branch there's type information available
2585 in tree->left->?type. If the op is e.g. '=' we extract the type
2586 information from there and propagate it to the right branch. */
2587 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2589 switch (tree->opval.op)
2592 /* delay right side for '?' operator since conditional macro
2593 expansions might rely on this */
2597 /* decorate right side for CALL (parameter list) in processParms();
2598 there is resultType available */
2602 /* don't allocate string if it is a sizeof argument */
2604 dtr = decorateType (tree->right, resultTypeProp);
2608 dtr = decorateType (tree->right, resultTypeProp);
2612 /* this is to take care of situations
2613 when the tree gets rewritten */
2614 if (dtl != tree->left)
2616 if (dtr != tree->right)
2618 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2622 /* depending on type of operator do */
2624 switch (tree->opval.op)
2626 /*------------------------------------------------------------------*/
2627 /*----------------------------*/
2629 /*----------------------------*/
2632 /* first check if this is a array or a pointer */
2633 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2635 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2636 goto errorTreeReturn;
2639 /* check if the type of the idx */
2640 if (!IS_INTEGRAL (RTYPE (tree)))
2642 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2643 goto errorTreeReturn;
2646 /* if the left is an rvalue then error */
2649 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2650 goto errorTreeReturn;
2653 if (IS_LITERAL (RTYPE (tree)))
2655 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2656 int arraySize = DCL_ELEM (LTYPE (tree));
2657 if (arraySize && arrayIndex >= arraySize)
2659 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2664 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2665 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2668 /*------------------------------------------------------------------*/
2669 /*----------------------------*/
2671 /*----------------------------*/
2673 /* if this is not a structure */
2674 if (!IS_STRUCT (LTYPE (tree)))
2676 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2677 goto errorTreeReturn;
2679 TTYPE (tree) = structElemType (LTYPE (tree),
2680 (tree->right->type == EX_VALUE ?
2681 tree->right->opval.val : NULL));
2682 TETYPE (tree) = getSpec (TTYPE (tree));
2685 /*------------------------------------------------------------------*/
2686 /*----------------------------*/
2687 /* struct/union pointer */
2688 /*----------------------------*/
2690 /* if not pointer to a structure */
2691 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2693 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2694 goto errorTreeReturn;
2697 if (!IS_STRUCT (LTYPE (tree)->next))
2699 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2700 goto errorTreeReturn;
2703 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2704 (tree->right->type == EX_VALUE ?
2705 tree->right->opval.val : NULL));
2706 TETYPE (tree) = getSpec (TTYPE (tree));
2708 /* adjust the storage class */
2709 switch (DCL_TYPE(tree->left->ftype)) {
2711 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2714 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2717 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2720 SPEC_SCLS (TETYPE (tree)) = 0;
2723 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2726 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2729 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2732 SPEC_SCLS (TETYPE (tree)) = 0;
2739 /* This breaks with extern declarations, bitfields, and perhaps other */
2740 /* cases (gcse). Let's leave this optimization disabled for now and */
2741 /* ponder if there's a safe way to do this. -- EEP */
2743 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2744 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2746 /* If defined struct type at addr var
2747 then rewrite (&struct var)->member
2749 and define membertype at (addr+offsetof(struct var,member)) temp
2752 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2753 AST_SYMBOL(tree->right));
2755 sym = newSymbol(genSymName (0), 0);
2756 sym->type = TTYPE (tree);
2757 sym->etype = getSpec(sym->type);
2758 sym->lineDef = tree->lineno;
2761 SPEC_STAT (sym->etype) = 1;
2762 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2764 SPEC_ABSA(sym->etype) = 1;
2765 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2768 AST_VALUE (tree) = symbolVal(sym);
2771 tree->type = EX_VALUE;
2779 /*------------------------------------------------------------------*/
2780 /*----------------------------*/
2781 /* ++/-- operation */
2782 /*----------------------------*/
2786 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2787 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2788 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2789 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2798 /*------------------------------------------------------------------*/
2799 /*----------------------------*/
2801 /*----------------------------*/
2802 case '&': /* can be unary */
2803 /* if right is NULL then unary operation */
2804 if (tree->right) /* not an unary operation */
2807 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2809 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2810 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2811 printTypeChain (LTYPE (tree), stderr);
2812 fprintf (stderr, ",");
2813 printTypeChain (RTYPE (tree), stderr);
2814 fprintf (stderr, "\n");
2815 goto errorTreeReturn;
2818 /* if they are both literal */
2819 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2821 tree->type = EX_VALUE;
2822 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2823 valFromType (RETYPE (tree)), '&');
2825 tree->right = tree->left = NULL;
2826 TETYPE (tree) = tree->opval.val->etype;
2827 TTYPE (tree) = tree->opval.val->type;
2831 /* see if this is a GETHBIT operation if yes
2834 ast *otree = optimizeGetHbit (tree, resultType);
2837 return decorateType (otree, RESULT_TYPE_NONE);
2840 /* see if this is a GETABIT operation if yes
2843 ast *otree = optimizeGetAbit (tree, resultType);
2846 return decorateType (otree, RESULT_TYPE_NONE);
2849 /* see if this is a GETBYTE operation if yes
2852 ast *otree = optimizeGetByte (tree, resultType);
2855 return decorateType (otree, RESULT_TYPE_NONE);
2858 /* see if this is a GETWORD operation if yes
2861 ast *otree = optimizeGetWord (tree, resultType);
2864 return decorateType (otree, RESULT_TYPE_NONE);
2867 /* if left is a literal exchange left & right */
2868 if (IS_LITERAL (LTYPE (tree)))
2870 ast *tTree = tree->left;
2871 tree->left = tree->right;
2872 tree->right = tTree;
2875 /* if right is a literal and */
2876 /* we can find a 2nd literal in an and-tree then */
2877 /* rearrange the tree */
2878 if (IS_LITERAL (RTYPE (tree)))
2881 ast *litTree = searchLitOp (tree, &parent, "&");
2885 ast *tTree = litTree->left;
2886 litTree->left = tree->right;
2887 tree->right = tTree;
2888 /* both operands in litTree are literal now */
2889 decorateType (parent, resultType);
2893 LRVAL (tree) = RRVAL (tree) = 1;
2895 TTYPE (tree) = computeType (LTYPE (tree),
2899 TETYPE (tree) = getSpec (TTYPE (tree));
2904 /*------------------------------------------------------------------*/
2905 /*----------------------------*/
2907 /*----------------------------*/
2908 p = newLink (DECLARATOR);
2909 /* if bit field then error */
2910 if (IS_BITVAR (tree->left->etype))
2912 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2913 goto errorTreeReturn;
2916 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2918 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2919 goto errorTreeReturn;
2922 if (IS_FUNC (LTYPE (tree)))
2924 // this ought to be ignored
2925 return (tree->left);
2928 if (IS_LITERAL(LTYPE(tree)))
2930 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2931 goto errorTreeReturn;
2936 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2937 goto errorTreeReturn;
2940 DCL_TYPE (p) = POINTER;
2941 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2942 DCL_TYPE (p) = CPOINTER;
2943 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2944 DCL_TYPE (p) = FPOINTER;
2945 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2946 DCL_TYPE (p) = PPOINTER;
2947 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2948 DCL_TYPE (p) = IPOINTER;
2949 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2950 DCL_TYPE (p) = EEPPOINTER;
2951 else if (SPEC_OCLS(tree->left->etype))
2952 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2954 DCL_TYPE (p) = POINTER;
2956 if (IS_AST_SYM_VALUE (tree->left))
2958 AST_SYMBOL (tree->left)->addrtaken = 1;
2959 AST_SYMBOL (tree->left)->allocreq = 1;
2962 p->next = LTYPE (tree);
2964 TETYPE (tree) = getSpec (TTYPE (tree));
2969 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2970 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2972 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2973 AST_SYMBOL(tree->left->right));
2974 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2975 valueFromLit(element->offset));
2978 tree->type = EX_VALUE;
2979 tree->values.literalFromCast = 1;
2985 /*------------------------------------------------------------------*/
2986 /*----------------------------*/
2988 /*----------------------------*/
2990 /* if the rewrite succeeds then don't go any further */
2992 ast *wtree = optimizeRRCRLC (tree);
2994 return decorateType (wtree, RESULT_TYPE_NONE);
2996 wtree = optimizeSWAP (tree);
2998 return decorateType (wtree, RESULT_TYPE_NONE);
3001 /* if left is a literal exchange left & right */
3002 if (IS_LITERAL (LTYPE (tree)))
3004 ast *tTree = tree->left;
3005 tree->left = tree->right;
3006 tree->right = tTree;
3009 /* if right is a literal and */
3010 /* we can find a 2nd literal in an or-tree then */
3011 /* rearrange the tree */
3012 if (IS_LITERAL (RTYPE (tree)))
3015 ast *litTree = searchLitOp (tree, &parent, "|");
3019 ast *tTree = litTree->left;
3020 litTree->left = tree->right;
3021 tree->right = tTree;
3022 /* both operands in tTree are literal now */
3023 decorateType (parent, resultType);
3028 /*------------------------------------------------------------------*/
3029 /*----------------------------*/
3031 /*----------------------------*/
3033 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3035 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3036 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3037 printTypeChain (LTYPE (tree), stderr);
3038 fprintf (stderr, ",");
3039 printTypeChain (RTYPE (tree), stderr);
3040 fprintf (stderr, "\n");
3041 goto errorTreeReturn;
3044 /* if they are both literal then rewrite the tree */
3045 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3047 tree->type = EX_VALUE;
3048 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3049 valFromType (RETYPE (tree)),
3051 tree->right = tree->left = NULL;
3052 TETYPE (tree) = tree->opval.val->etype;
3053 TTYPE (tree) = tree->opval.val->type;
3057 /* if left is a literal exchange left & right */
3058 if (IS_LITERAL (LTYPE (tree)))
3060 ast *tTree = tree->left;
3061 tree->left = tree->right;
3062 tree->right = tTree;
3065 /* if right is a literal and */
3066 /* we can find a 2nd literal in a xor-tree then */
3067 /* rearrange the tree */
3068 if (IS_LITERAL (RTYPE (tree)) &&
3069 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3072 ast *litTree = searchLitOp (tree, &parent, "^");
3076 ast *tTree = litTree->left;
3077 litTree->left = tree->right;
3078 tree->right = tTree;
3079 /* both operands in litTree are literal now */
3080 decorateType (parent, resultType);
3084 LRVAL (tree) = RRVAL (tree) = 1;
3086 TTYPE (tree) = computeType (LTYPE (tree),
3090 TETYPE (tree) = getSpec (TTYPE (tree));
3094 /*------------------------------------------------------------------*/
3095 /*----------------------------*/
3097 /*----------------------------*/
3099 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3101 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3102 goto errorTreeReturn;
3104 /* if they are both literal then */
3105 /* rewrite the tree */
3106 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3108 tree->type = EX_VALUE;
3109 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3110 valFromType (RETYPE (tree)));
3111 tree->right = tree->left = NULL;
3112 TETYPE (tree) = getSpec (TTYPE (tree) =
3113 tree->opval.val->type);
3117 LRVAL (tree) = RRVAL (tree) = 1;
3119 TETYPE (tree) = getSpec (TTYPE (tree) =
3120 computeType (LTYPE (tree),
3125 /* if right is a literal and */
3126 /* left is also a division by a literal then */
3127 /* rearrange the tree */
3128 if (IS_LITERAL (RTYPE (tree))
3129 /* avoid infinite loop */
3130 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3133 ast *litTree = searchLitOp (tree, &parent, "/");
3136 if (IS_LITERAL (RTYPE (litTree)))
3140 litTree->right = newNode ('*',
3142 copyAst (tree->right));
3143 litTree->right->filename = tree->filename;
3144 litTree->right->lineno = tree->lineno;
3146 tree->right->opval.val = constCharVal (1);
3147 decorateType (parent, resultType);
3151 /* litTree->left is literal: no gcse possible.
3152 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3153 this would cause an infinit loop. */
3154 parent->decorated = 1;
3155 decorateType (litTree, resultType);
3162 /*------------------------------------------------------------------*/
3163 /*----------------------------*/
3165 /*----------------------------*/
3167 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3169 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3170 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3171 printTypeChain (LTYPE (tree), stderr);
3172 fprintf (stderr, ",");
3173 printTypeChain (RTYPE (tree), stderr);
3174 fprintf (stderr, "\n");
3175 goto errorTreeReturn;
3177 /* if they are both literal then */
3178 /* rewrite the tree */
3179 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3181 tree->type = EX_VALUE;
3182 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3183 valFromType (RETYPE (tree)));
3184 tree->right = tree->left = NULL;
3185 TETYPE (tree) = getSpec (TTYPE (tree) =
3186 tree->opval.val->type);
3189 LRVAL (tree) = RRVAL (tree) = 1;
3190 TETYPE (tree) = getSpec (TTYPE (tree) =
3191 computeType (LTYPE (tree),
3197 /*------------------------------------------------------------------*/
3198 /*----------------------------*/
3199 /* address dereference */
3200 /*----------------------------*/
3201 case '*': /* can be unary : if right is null then unary operation */
3204 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3206 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3207 goto errorTreeReturn;
3212 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3213 goto errorTreeReturn;
3215 if (IS_ADDRESS_OF_OP(tree->left))
3217 /* replace *&obj with obj */
3218 return tree->left->left;
3220 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3221 TETYPE (tree) = getSpec (TTYPE (tree));
3222 /* adjust the storage class */
3223 switch (DCL_TYPE(tree->left->ftype)) {
3225 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3228 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3231 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3234 SPEC_SCLS (TETYPE (tree)) = 0;
3237 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3240 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3243 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3246 SPEC_SCLS (TETYPE (tree)) = 0;
3255 /*------------------------------------------------------------------*/
3256 /*----------------------------*/
3257 /* multiplication */
3258 /*----------------------------*/
3259 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3261 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3262 goto errorTreeReturn;
3265 /* if they are both literal then */
3266 /* rewrite the tree */
3267 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3269 tree->type = EX_VALUE;
3270 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3271 valFromType (RETYPE (tree)));
3272 tree->right = tree->left = NULL;
3273 TETYPE (tree) = getSpec (TTYPE (tree) =
3274 tree->opval.val->type);
3278 /* if left is a literal exchange left & right */
3279 if (IS_LITERAL (LTYPE (tree)))
3281 ast *tTree = tree->left;
3282 tree->left = tree->right;
3283 tree->right = tTree;
3286 /* if right is a literal and */
3287 /* we can find a 2nd literal in a mul-tree then */
3288 /* rearrange the tree */
3289 if (IS_LITERAL (RTYPE (tree)))
3292 ast *litTree = searchLitOp (tree, &parent, "*");
3296 ast *tTree = litTree->left;
3297 litTree->left = tree->right;
3298 tree->right = tTree;
3299 /* both operands in litTree are literal now */
3300 decorateType (parent, resultType);
3304 LRVAL (tree) = RRVAL (tree) = 1;
3305 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3306 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3307 TETYPE (tree) = getSpec (TTYPE (tree) =
3308 computeType (LTYPE (tree),
3315 /*------------------------------------------------------------------*/
3316 /*----------------------------*/
3317 /* unary '+' operator */
3318 /*----------------------------*/
3323 if (!IS_ARITHMETIC (LTYPE (tree)))
3325 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3326 goto errorTreeReturn;
3329 /* if left is a literal then do it */
3330 if (IS_LITERAL (LTYPE (tree)))
3332 tree->type = EX_VALUE;
3333 tree->opval.val = valFromType (LETYPE (tree));
3335 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3339 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3343 /*------------------------------------------------------------------*/
3344 /*----------------------------*/
3346 /*----------------------------*/
3348 /* this is not a unary operation */
3349 /* if both pointers then problem */
3350 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3351 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3353 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3354 goto errorTreeReturn;
3357 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3358 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3360 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3361 goto errorTreeReturn;
3364 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3365 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3367 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3368 goto errorTreeReturn;
3370 /* if they are both literal then */
3371 /* rewrite the tree */
3372 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3374 tree->type = EX_VALUE;
3375 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3376 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3377 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3378 valFromType (RETYPE (tree)));
3379 tree->right = tree->left = NULL;
3380 TETYPE (tree) = getSpec (TTYPE (tree) =
3381 tree->opval.val->type);
3385 /* if the right is a pointer or left is a literal
3386 xchange left & right */
3387 if (IS_ARRAY (RTYPE (tree)) ||
3388 IS_PTR (RTYPE (tree)) ||
3389 IS_LITERAL (LTYPE (tree)))
3391 ast *tTree = tree->left;
3392 tree->left = tree->right;
3393 tree->right = tTree;
3396 /* if right is a literal and */
3397 /* left is also an addition/subtraction with a literal then */
3398 /* rearrange the tree */
3399 if (IS_LITERAL (RTYPE (tree)))
3401 ast *litTree, *parent;
3402 litTree = searchLitOp (tree, &parent, "+-");
3405 if (litTree->opval.op == '+')
3409 ast *tTree = litTree->left;
3410 litTree->left = tree->right;
3411 tree->right = tree->left;
3414 else if (litTree->opval.op == '-')
3416 if (IS_LITERAL (RTYPE (litTree)))
3420 ast *tTree = litTree->left;
3421 litTree->left = tree->right;
3422 tree->right = tTree;
3428 ast *tTree = litTree->right;
3429 litTree->right = tree->right;
3430 tree->right = tTree;
3431 litTree->opval.op = '+';
3432 tree->opval.op = '-';
3435 decorateType (parent, resultType);
3439 LRVAL (tree) = RRVAL (tree) = 1;
3440 /* if the left is a pointer */
3441 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3442 TETYPE (tree) = getSpec (TTYPE (tree) =
3446 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3447 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3448 TETYPE (tree) = getSpec (TTYPE (tree) =
3449 computeType (LTYPE (tree),
3457 /*------------------------------------------------------------------*/
3458 /*----------------------------*/
3460 /*----------------------------*/
3461 case '-': /* can be unary */
3462 /* if right is null then unary */
3466 if (!IS_ARITHMETIC (LTYPE (tree)))
3468 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3469 goto errorTreeReturn;
3472 /* if left is a literal then do it */
3473 if (IS_LITERAL (LTYPE (tree)))
3475 tree->type = EX_VALUE;
3476 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3478 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3481 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3482 TETYPE (tree) = getSpec (TTYPE (tree) =
3483 computeType (LTYPE (tree),
3491 /*------------------------------------------------------------------*/
3492 /*----------------------------*/
3494 /*----------------------------*/
3496 if (!(IS_PTR (LTYPE (tree)) ||
3497 IS_ARRAY (LTYPE (tree)) ||
3498 IS_ARITHMETIC (LTYPE (tree))))
3500 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3501 goto errorTreeReturn;
3504 if (!(IS_PTR (RTYPE (tree)) ||
3505 IS_ARRAY (RTYPE (tree)) ||
3506 IS_ARITHMETIC (RTYPE (tree))))
3508 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3509 goto errorTreeReturn;
3512 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3513 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3514 IS_INTEGRAL (RTYPE (tree))))
3516 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3517 goto errorTreeReturn;
3520 /* if they are both literal then */
3521 /* rewrite the tree */
3522 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3524 tree->type = EX_VALUE;
3525 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3526 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3527 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3528 valFromType (RETYPE (tree)));
3529 tree->right = tree->left = NULL;
3530 TETYPE (tree) = getSpec (TTYPE (tree) =
3531 tree->opval.val->type);
3535 /* if the left & right are equal then zero */
3536 if (isAstEqual (tree->left, tree->right))
3538 tree->type = EX_VALUE;
3539 tree->left = tree->right = NULL;
3540 tree->opval.val = constCharVal (0);
3541 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3545 /* if both of them are pointers or arrays then */
3546 /* the result is going to be an integer */
3547 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3548 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3549 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3551 /* if only the left is a pointer */
3552 /* then result is a pointer */
3553 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3554 TETYPE (tree) = getSpec (TTYPE (tree) =
3558 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3559 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3561 TETYPE (tree) = getSpec (TTYPE (tree) =
3562 computeType (LTYPE (tree),
3568 LRVAL (tree) = RRVAL (tree) = 1;
3570 /* if right is a literal and */
3571 /* left is also an addition/subtraction with a literal then */
3572 /* rearrange the tree */
3573 if (IS_LITERAL (RTYPE (tree))
3574 /* avoid infinite loop */
3575 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3577 ast *litTree, *litParent;
3578 litTree = searchLitOp (tree, &litParent, "+-");
3581 if (litTree->opval.op == '+')
3585 ast *tTree = litTree->left;
3586 litTree->left = litTree->right;
3587 litTree->right = tree->right;
3588 tree->right = tTree;
3589 tree->opval.op = '+';
3590 litTree->opval.op = '-';
3592 else if (litTree->opval.op == '-')
3594 if (IS_LITERAL (RTYPE (litTree)))
3598 ast *tTree = litTree->left;
3599 litTree->left = tree->right;
3600 tree->right = litParent->left;
3601 litParent->left = tTree;
3602 litTree->opval.op = '+';
3604 tree->decorated = 0;
3605 decorateType (tree, resultType);
3611 ast *tTree = litTree->right;
3612 litTree->right = tree->right;
3613 tree->right = tTree;
3616 decorateType (litParent, resultType);
3621 /*------------------------------------------------------------------*/
3622 /*----------------------------*/
3624 /*----------------------------*/
3626 /* can be only integral type */
3627 if (!IS_INTEGRAL (LTYPE (tree)))
3629 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3630 goto errorTreeReturn;
3633 /* if left is a literal then do it */
3634 if (IS_LITERAL (LTYPE (tree)))
3636 tree->type = EX_VALUE;
3637 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3639 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3640 return addCast (tree, resultTypeProp, TRUE);
3643 if (resultType == RESULT_TYPE_BIT &&
3644 IS_UNSIGNED (tree->left->etype) &&
3645 getSize (tree->left->etype) < INTSIZE)
3647 /* promotion rules are responsible for this strange result:
3648 bit -> int -> ~int -> bit
3649 uchar -> int -> ~int -> bit
3651 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3653 /* optimize bit-result, even if we optimize a buggy source */
3654 tree->type = EX_VALUE;
3655 tree->opval.val = constCharVal (1);
3658 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3660 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3663 /*------------------------------------------------------------------*/
3664 /*----------------------------*/
3666 /*----------------------------*/
3668 /* can be pointer */
3669 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3670 !IS_PTR (LTYPE (tree)) &&
3671 !IS_ARRAY (LTYPE (tree)))
3673 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3674 goto errorTreeReturn;
3677 /* if left is another '!' */
3678 if (IS_AST_NOT_OPER (tree->left))
3680 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3682 /* replace double '!!X' by 'X' */
3683 return tree->left->left;
3685 /* remove double '!!X' by 'X ? 1 : 0' */
3686 tree->opval.op = '?';
3687 tree->left = tree->left->left;
3688 tree->right = newNode (':',
3689 newAst_VALUE (constCharVal (1)),
3690 newAst_VALUE (constCharVal (0)));
3691 tree->right->filename = tree->filename;
3692 tree->right->lineno = tree->lineno;
3693 tree->decorated = 0;
3694 return decorateType (tree, resultType);
3697 /* if left is a literal then do it */
3698 if (IS_LITERAL (LTYPE (tree)))
3700 tree->type = EX_VALUE;
3701 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3703 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3707 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3710 /*------------------------------------------------------------------*/
3711 /*----------------------------*/
3713 /*----------------------------*/
3717 TTYPE (tree) = LTYPE (tree);
3718 TETYPE (tree) = LETYPE (tree);
3723 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3727 TTYPE (tree) = TETYPE (tree) = newCharLink();
3731 TTYPE (tree) = TETYPE (tree) = newIntLink();
3736 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3738 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3739 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3740 printTypeChain (LTYPE (tree), stderr);
3741 fprintf (stderr, ",");
3742 printTypeChain (RTYPE (tree), stderr);
3743 fprintf (stderr, "\n");
3744 goto errorTreeReturn;
3747 /* make smaller type only if it's a LEFT_OP */
3748 if (tree->opval.op == LEFT_OP)
3749 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3751 /* if they are both literal then */
3752 /* rewrite the tree */
3753 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3755 tree->type = EX_VALUE;
3756 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3757 valFromType (RETYPE (tree)),
3758 (tree->opval.op == LEFT_OP ? 1 : 0));
3759 tree->right = tree->left = NULL;
3760 TETYPE (tree) = getSpec (TTYPE (tree) =
3761 tree->opval.val->type);
3765 /* see if this is a GETBYTE operation if yes
3768 ast *otree = optimizeGetByte (tree, resultType);
3771 return decorateType (otree, RESULT_TYPE_NONE);
3774 /* see if this is a GETWORD operation if yes
3777 ast *otree = optimizeGetWord (tree, resultType);
3780 return decorateType (otree, RESULT_TYPE_NONE);
3783 LRVAL (tree) = RRVAL (tree) = 1;
3784 if (tree->opval.op == LEFT_OP)
3786 TETYPE (tree) = getSpec (TTYPE (tree) =
3787 computeType (LTYPE (tree),
3794 /* no promotion necessary */
3795 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3796 if (IS_LITERAL (TTYPE (tree)))
3797 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3800 /* if only the right side is a literal & we are
3801 shifting more than size of the left operand then zero */
3802 if (IS_LITERAL (RTYPE (tree)) &&
3803 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3804 (getSize (TETYPE (tree)) * 8))
3806 if (tree->opval.op==LEFT_OP ||
3807 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3809 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3810 (tree->opval.op == LEFT_OP ? "left" : "right"));
3811 tree->type = EX_VALUE;
3812 tree->left = tree->right = NULL;
3813 tree->opval.val = constCharVal (0);
3814 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3821 /*------------------------------------------------------------------*/
3822 /*----------------------------*/
3824 /*----------------------------*/
3825 case CAST: /* change the type */
3826 /* cannot cast to an aggregate type */
3827 if (IS_AGGREGATE (LTYPE (tree)))
3829 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3830 goto errorTreeReturn;
3833 /* make sure the type is complete and sane */
3834 changePointer(LTYPE(tree));
3835 checkTypeSanity(LETYPE(tree), "(cast)");
3837 /* if 'from' and 'to' are the same remove the superfluous cast, */
3838 /* this helps other optimizations */
3839 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3844 /* If code memory is read only, then pointers to code memory */
3845 /* implicitly point to constants -- make this explicit */
3847 sym_link *t = LTYPE(tree);
3848 while (t && t->next)
3850 if (IS_CODEPTR(t) && port->mem.code_ro)
3852 if (IS_SPEC(t->next))
3853 SPEC_CONST (t->next) = 1;
3855 DCL_PTR_CONST (t->next) = 1;
3862 /* if the right is a literal replace the tree */
3863 if (IS_LITERAL (RETYPE (tree))) {
3864 if (!IS_PTR (LTYPE (tree))) {
3865 tree->type = EX_VALUE;
3867 valCastLiteral (LTYPE (tree),
3868 floatFromVal (valFromType (RETYPE (tree))));
3871 TTYPE (tree) = tree->opval.val->type;
3872 tree->values.literalFromCast = 1;
3873 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3874 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3875 sym_link *rest = LTYPE(tree)->next;
3876 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3877 TTYPE(tree) = newLink(DECLARATOR);
3878 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3879 TTYPE(tree)->next = rest;
3880 tree->left->opval.lnk = TTYPE(tree);
3883 TTYPE (tree) = LTYPE (tree);
3887 TTYPE (tree) = LTYPE (tree);
3891 #if 0 // this is already checked, now this could be explicit
3892 /* if pointer to struct then check names */
3893 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3894 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3895 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3897 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3898 SPEC_STRUCT(LETYPE(tree))->tag);
3901 if (IS_ADDRESS_OF_OP(tree->right)
3902 && IS_AST_SYM_VALUE (tree->right->left)
3903 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3905 symbol * sym = AST_SYMBOL (tree->right->left);
3906 unsigned int gptype = 0;
3907 unsigned int addr = SPEC_ADDR (sym->etype);
3909 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3910 || TARGET_IS_PIC16) )
3912 switch (SPEC_SCLS (sym->etype))
3915 gptype = GPTYPE_CODE;
3918 gptype = GPTYPE_FAR;
3922 gptype = GPTYPE_NEAR;
3925 gptype = GPTYPE_XSTACK;
3930 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3931 gptype = GPTYPE_NEAR;
3933 addr |= gptype << (8*(GPTRSIZE - 1));
3936 tree->type = EX_VALUE;
3938 valCastLiteral (LTYPE (tree), addr);
3939 TTYPE (tree) = tree->opval.val->type;
3940 TETYPE (tree) = getSpec (TTYPE (tree));
3943 tree->values.literalFromCast = 1;
3947 /* handle offsetof macro: */
3948 /* #define offsetof(TYPE, MEMBER) \ */
3949 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3950 if (IS_ADDRESS_OF_OP(tree->right)
3951 && IS_AST_OP (tree->right->left)
3952 && tree->right->left->opval.op == PTR_OP
3953 && IS_AST_OP (tree->right->left->left)
3954 && tree->right->left->left->opval.op == CAST
3955 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3957 symbol *element = getStructElement (
3958 SPEC_STRUCT (LETYPE(tree->right->left)),
3959 AST_SYMBOL(tree->right->left->right)
3963 tree->type = EX_VALUE;
3964 tree->opval.val = valCastLiteral (
3967 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3970 TTYPE (tree) = tree->opval.val->type;
3971 TETYPE (tree) = getSpec (TTYPE (tree));
3978 /* if the right is a literal replace the tree */
3979 if (IS_LITERAL (RETYPE (tree))) {
3981 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3982 /* rewrite (type *)litaddr
3984 and define type at litaddr temp
3985 (but only if type's storage class is not generic)
3987 ast *newTree = newNode ('&', NULL, NULL);
3990 TTYPE (newTree) = LTYPE (tree);
3991 TETYPE (newTree) = getSpec(LTYPE (tree));
3993 /* define a global symbol at the casted address*/
3994 sym = newSymbol(genSymName (0), 0);
3995 sym->type = LTYPE (tree)->next;
3997 sym->type = newLink (V_VOID);
3998 sym->etype = getSpec(sym->type);
3999 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4000 sym->lineDef = tree->lineno;
4003 SPEC_STAT (sym->etype) = 1;
4004 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4005 SPEC_ABSA(sym->etype) = 1;
4006 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4009 newTree->left = newAst_VALUE(symbolVal(sym));
4010 newTree->left->filename = tree->filename;
4011 newTree->left->lineno = tree->lineno;
4012 LTYPE (newTree) = sym->type;
4013 LETYPE (newTree) = sym->etype;
4014 LLVAL (newTree) = 1;
4015 LRVAL (newTree) = 0;
4016 TLVAL (newTree) = 1;
4020 if (!IS_PTR (LTYPE (tree))) {
4021 tree->type = EX_VALUE;
4023 valCastLiteral (LTYPE (tree),
4024 floatFromVal (valFromType (RTYPE (tree))));
4025 TTYPE (tree) = tree->opval.val->type;
4028 tree->values.literalFromCast = 1;
4029 TETYPE (tree) = getSpec (TTYPE (tree));
4033 TTYPE (tree) = LTYPE (tree);
4037 TETYPE (tree) = getSpec (TTYPE (tree));
4041 /*------------------------------------------------------------------*/
4042 /*----------------------------*/
4043 /* logical &&, || */
4044 /*----------------------------*/
4047 /* each must be arithmetic type or be a pointer */
4048 if (!IS_PTR (LTYPE (tree)) &&
4049 !IS_ARRAY (LTYPE (tree)) &&
4050 !IS_INTEGRAL (LTYPE (tree)))
4052 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4053 goto errorTreeReturn;
4056 if (!IS_PTR (RTYPE (tree)) &&
4057 !IS_ARRAY (RTYPE (tree)) &&
4058 !IS_INTEGRAL (RTYPE (tree)))
4060 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4061 goto errorTreeReturn;
4063 /* if they are both literal then */
4064 /* rewrite the tree */
4065 if (IS_LITERAL (RTYPE (tree)) &&
4066 IS_LITERAL (LTYPE (tree)))
4068 tree->type = EX_VALUE;
4069 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4070 valFromType (RTYPE (tree)),
4072 tree->right = tree->left = NULL;
4073 TETYPE (tree) = getSpec (TTYPE (tree) =
4074 tree->opval.val->type);
4077 LRVAL (tree) = RRVAL (tree) = 1;
4078 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4081 /*------------------------------------------------------------------*/
4082 /*----------------------------*/
4083 /* comparison operators */
4084 /*----------------------------*/
4092 ast *lt = optimizeCompare (tree);
4098 /* if they are pointers they must be castable */
4099 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4101 if (tree->opval.op==EQ_OP &&
4102 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4103 // we cannot cast a gptr to a !gptr: switch the leaves
4104 struct ast *s=tree->left;
4105 tree->left=tree->right;
4108 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4110 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4111 fprintf (stderr, "comparing type ");
4112 printTypeChain (LTYPE (tree), stderr);
4113 fprintf (stderr, "to type ");
4114 printTypeChain (RTYPE (tree), stderr);
4115 fprintf (stderr, "\n");
4116 goto errorTreeReturn;
4119 /* else they should be promotable to one another */
4122 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4123 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4125 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4127 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4128 fprintf (stderr, "comparing type ");
4129 printTypeChain (LTYPE (tree), stderr);
4130 fprintf (stderr, "to type ");
4131 printTypeChain (RTYPE (tree), stderr);
4132 fprintf (stderr, "\n");
4133 goto errorTreeReturn;
4138 CCR_RESULT ccr_result = CCR_OK;
4140 /* if left is integral and right is literal
4141 then check constant range */
4142 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4143 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4144 tree->opval.op, FALSE);
4145 if (ccr_result == CCR_OK &&
4146 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4147 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4148 tree->opval.op, TRUE);
4151 case CCR_ALWAYS_TRUE:
4152 case CCR_ALWAYS_FALSE:
4153 if (!options.lessPedantic)
4154 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4155 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4156 return decorateType (newAst_VALUE (constCharVal (
4157 ccr_result == CCR_ALWAYS_TRUE ? 1 : 0)),
4165 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4166 if (tree->opval.op == '>' &&
4167 SPEC_USIGN(LETYPE(tree)) &&
4168 IS_LITERAL(RTYPE(tree)) &&
4169 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4171 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4173 /* the parent is an ifx: */
4174 /* if (unsigned value) */
4178 /* (unsigned value) ? 1 : 0 */
4179 tree->opval.op = '?';
4180 tree->right = newNode (':',
4181 newAst_VALUE (constCharVal (1)),
4182 tree->right); /* val 0 */
4183 tree->right->filename = tree->filename;
4184 tree->right->lineno = tree->lineno;
4185 tree->right->left->filename = tree->filename;
4186 tree->right->left->lineno = tree->lineno;
4187 tree->decorated = 0;
4188 return decorateType (tree, resultType);
4191 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4192 if (IS_LITERAL(RTYPE(tree)) &&
4193 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4194 tree->opval.op == EQ_OP &&
4195 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4197 tree->opval.op = '!';
4199 tree->decorated = 0;
4200 return decorateType (tree, resultType);
4203 /* if they are both literal then */
4204 /* rewrite the tree */
4205 if (IS_LITERAL (RTYPE (tree)) &&
4206 IS_LITERAL (LTYPE (tree)))
4208 tree->type = EX_VALUE;
4209 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4210 valFromType (RETYPE (tree)),
4212 tree->right = tree->left = NULL;
4213 TETYPE (tree) = getSpec (TTYPE (tree) =
4214 tree->opval.val->type);
4218 /* if one is 'signed char ' and the other one is 'unsigned char' */
4219 /* it's necessary to promote to int */
4220 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4221 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4223 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4224 if it's possible to use a 'signed char' */
4226 /* is left a 'unsigned char'? */
4227 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4228 /* the value range of a 'unsigned char' is 0...255;
4229 if the actual value is < 128 it can be changed to signed */
4230 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4232 /* now we've got 2 'signed char'! */
4233 SPEC_USIGN (RETYPE (tree)) = 0;
4235 /* same test for the left operand: */
4236 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4237 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4239 SPEC_USIGN (LETYPE (tree)) = 0;
4243 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4244 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4245 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4249 LRVAL (tree) = RRVAL (tree) = 1;
4250 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4252 /* condition transformations */
4254 unsigned transformedOp = 0;
4256 switch (tree->opval.op)
4258 case '<': /* transform (a < b) to !(a >= b) */
4260 transformedOp = GE_OP;
4262 case '>': /* transform (a > b) to !(a <= b) */
4264 transformedOp = LE_OP;
4266 case LE_OP: /* transform (a <= b) to !(a > b) */
4268 transformedOp = '>';
4270 case GE_OP: /* transform (a >= b) to !(a < b) */
4272 transformedOp = '<';
4274 case NE_OP: /* transform (a != b) to !(a == b) */
4276 transformedOp = EQ_OP;
4278 case EQ_OP: /* transform (a == b) to !(a != b) */
4280 transformedOp = NE_OP;
4287 tree->opval.op = transformedOp;
4288 tree->decorated = 0;
4289 tree = newNode ('!', tree, NULL);
4290 tree->filename = tree->left->filename;
4291 tree->lineno = tree->left->lineno;
4292 return decorateType (tree, resultType);
4298 /*------------------------------------------------------------------*/
4299 /*----------------------------*/
4301 /*----------------------------*/
4302 case SIZEOF: /* evaluate wihout code generation */
4303 /* change the type to a integer */
4305 int size = getSize (tree->right->ftype);
4307 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4308 if (!size && !IS_VOID(tree->right->ftype))
4309 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4311 tree->type = EX_VALUE;
4312 tree->opval.val = constVal (buffer);
4313 tree->right = tree->left = NULL;
4314 TETYPE (tree) = getSpec (TTYPE (tree) =
4315 tree->opval.val->type);
4319 /*------------------------------------------------------------------*/
4320 /*----------------------------*/
4322 /*----------------------------*/
4324 /* return typeof enum value */
4325 tree->type = EX_VALUE;
4328 if (IS_SPEC(tree->right->ftype)) {
4329 switch (SPEC_NOUN(tree->right->ftype)) {
4331 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4332 else typeofv = TYPEOF_INT;
4335 typeofv = TYPEOF_FLOAT;
4338 typeofv = TYPEOF_FIXED16X16;
4341 typeofv = TYPEOF_CHAR;
4344 typeofv = TYPEOF_VOID;
4347 typeofv = TYPEOF_STRUCT;
4350 typeofv = TYPEOF_BITFIELD;
4353 typeofv = TYPEOF_BIT;
4356 typeofv = TYPEOF_SBIT;
4362 switch (DCL_TYPE(tree->right->ftype)) {
4364 typeofv = TYPEOF_POINTER;
4367 typeofv = TYPEOF_FPOINTER;
4370 typeofv = TYPEOF_CPOINTER;
4373 typeofv = TYPEOF_GPOINTER;
4376 typeofv = TYPEOF_PPOINTER;
4379 typeofv = TYPEOF_IPOINTER;
4382 typeofv = TYPEOF_ARRAY;
4385 typeofv = TYPEOF_FUNCTION;
4391 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4392 tree->opval.val = constVal (buffer);
4393 tree->right = tree->left = NULL;
4394 TETYPE (tree) = getSpec (TTYPE (tree) =
4395 tree->opval.val->type);
4398 /*------------------------------------------------------------------*/
4399 /*----------------------------*/
4400 /* conditional operator '?' */
4401 /*----------------------------*/
4403 /* the type is value of the colon operator (on the right) */
4404 assert (IS_COLON_OP (tree->right));
4406 /* If already known then replace the tree : optimizer will do it
4407 but faster to do it here. If done before decorating tree->right
4408 this can save generating unused const strings. */
4409 if (IS_LITERAL (LTYPE (tree)))
4411 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4412 return decorateType (tree->right->left, resultTypeProp);
4414 return decorateType (tree->right->right, resultTypeProp);
4417 tree->right = decorateType (tree->right, resultTypeProp);
4419 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4420 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4422 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4423 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4425 if ((valTrue != 0) && (valFalse == 0))
4427 /* assign cond to result */
4428 tree->left->decorated = 0;
4429 return decorateType (tree->left, resultTypeProp);
4431 else if ((valTrue == 0) && (valFalse != 0))
4433 /* assign !cond to result */
4434 tree->opval.op = '!';
4435 tree->decorated = 0;
4437 return decorateType (tree, resultTypeProp);
4441 /* they have the same boolean value, make them equal */
4442 tree->right->left = tree->right->right;
4446 /* if they are equal then replace the tree */
4447 if (isAstEqual (tree->right->left, tree->right->right))
4449 return tree->right->left;
4452 TTYPE (tree) = RTYPE (tree);
4453 TETYPE (tree) = getSpec (TTYPE (tree));
4457 /* if they don't match we have a problem */
4458 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4459 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4461 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4462 goto errorTreeReturn;
4465 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4466 resultType, tree->opval.op);
4467 TETYPE (tree) = getSpec (TTYPE (tree));
4471 #if 0 // assignment operators are converted by the parser
4472 /*------------------------------------------------------------------*/
4473 /*----------------------------*/
4474 /* assignment operators */
4475 /*----------------------------*/
4478 /* for these it must be both must be integral */
4479 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4480 !IS_ARITHMETIC (RTYPE (tree)))
4482 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4483 goto errorTreeReturn;
4486 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4488 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4489 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4493 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4494 goto errorTreeReturn;
4505 /* for these it must be both must be integral */
4506 if (!IS_INTEGRAL (LTYPE (tree)) ||
4507 !IS_INTEGRAL (RTYPE (tree)))
4509 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4510 goto errorTreeReturn;
4513 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4515 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4516 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4520 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4521 goto errorTreeReturn;
4527 /*------------------------------------------------------------------*/
4528 /*----------------------------*/
4530 /*----------------------------*/
4532 if (!(IS_PTR (LTYPE (tree)) ||
4533 IS_ARITHMETIC (LTYPE (tree))))
4535 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4536 goto errorTreeReturn;
4539 if (!(IS_PTR (RTYPE (tree)) ||
4540 IS_ARITHMETIC (RTYPE (tree))))
4542 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4543 goto errorTreeReturn;
4546 TETYPE (tree) = getSpec (TTYPE (tree) =
4547 computeType (LTYPE (tree),
4552 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4553 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4557 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4558 goto errorTreeReturn;
4564 /*------------------------------------------------------------------*/
4565 /*----------------------------*/
4567 /*----------------------------*/
4569 /* this is not a unary operation */
4570 /* if both pointers then problem */
4571 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4573 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4574 goto errorTreeReturn;
4577 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4579 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4580 goto errorTreeReturn;
4583 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4585 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4586 goto errorTreeReturn;
4589 TETYPE (tree) = getSpec (TTYPE (tree) =
4590 computeType (LTYPE (tree),
4595 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4596 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4600 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4601 goto errorTreeReturn;
4604 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4605 tree->opval.op = '=';
4610 /*------------------------------------------------------------------*/
4611 /*----------------------------*/
4612 /* straight assignemnt */
4613 /*----------------------------*/
4615 /* cannot be an aggregate */
4616 if (IS_AGGREGATE (LTYPE (tree)))
4618 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4619 goto errorTreeReturn;
4622 /* they should either match or be castable */
4623 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4625 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4626 printFromToType(RTYPE(tree),LTYPE(tree));
4629 /* if the left side of the tree is of type void
4630 then report error */
4631 if (IS_VOID (LTYPE (tree)))
4633 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4634 printFromToType(RTYPE(tree), LTYPE(tree));
4637 TETYPE (tree) = getSpec (TTYPE (tree) =
4641 if (!tree->initMode ) {
4642 if (IS_CONSTANT(LTYPE(tree)))
4643 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4647 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4648 goto errorTreeReturn;
4653 /*------------------------------------------------------------------*/
4654 /*----------------------------*/
4655 /* comma operator */
4656 /*----------------------------*/
4658 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4661 /*------------------------------------------------------------------*/
4662 /*----------------------------*/
4664 /*----------------------------*/
4667 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4668 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4670 if (tree->left->opval.op == '*' && !tree->left->right)
4671 tree->left = tree->left->left;
4674 /* require a function or pointer to function */
4675 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4677 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4678 goto errorTreeReturn;
4681 /* if there are parms, make sure that
4682 parms are decorate / process / reverse only once */
4684 !tree->right->decorated)
4689 if (IS_FUNCPTR (LTYPE (tree)))
4691 functype = LTYPE (tree)->next;
4692 processFuncPtrArgs (functype);
4695 functype = LTYPE (tree);
4697 if (processParms (tree->left, FUNC_ARGS(functype),
4698 &tree->right, &parmNumber, TRUE))
4700 goto errorTreeReturn;
4703 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4704 !IFFUNC_ISBUILTIN(functype))
4706 reverseParms (tree->right);
4709 TTYPE (tree) = functype->next;
4710 TETYPE (tree) = getSpec (TTYPE (tree));
4714 /*------------------------------------------------------------------*/
4715 /*----------------------------*/
4716 /* return statement */
4717 /*----------------------------*/
4722 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4724 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4725 printFromToType (RTYPE(tree), currFunc->type->next);
4726 goto errorTreeReturn;
4729 if (IS_VOID (currFunc->type->next)
4731 !IS_VOID (RTYPE (tree)))
4733 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4734 goto errorTreeReturn;
4737 /* if there is going to be a casting required then add it */
4738 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4741 decorateType (newNode (CAST,
4742 newAst_LINK (copyLinkChain (currFunc->type->next)),
4752 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4754 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4755 goto errorTreeReturn;
4758 TTYPE (tree) = TETYPE (tree) = NULL;
4761 /*------------------------------------------------------------------*/
4762 /*----------------------------*/
4763 /* switch statement */
4764 /*----------------------------*/
4766 /* the switch value must be an integer */
4767 if (!IS_INTEGRAL (LTYPE (tree)))
4769 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4770 goto errorTreeReturn;
4773 TTYPE (tree) = TETYPE (tree) = NULL;
4776 /*------------------------------------------------------------------*/
4777 /*----------------------------*/
4779 /*----------------------------*/
4781 tree->left = backPatchLabels (tree->left,
4784 TTYPE (tree) = TETYPE (tree) = NULL;
4787 /*------------------------------------------------------------------*/
4788 /*----------------------------*/
4790 /*----------------------------*/
4793 AST_FOR (tree, initExpr) = decorateType (
4794 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4795 AST_FOR (tree, condExpr) = decorateType (
4796 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4797 AST_FOR (tree, loopExpr) = decorateType (
4798 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4800 /* if the for loop is reversible then
4801 reverse it otherwise do what we normally
4807 if (isLoopReversible (tree, &sym, &init, &end))
4808 return reverseLoop (tree, sym, init, end);
4810 return decorateType (createFor (AST_FOR (tree, trueLabel),
4811 AST_FOR (tree, continueLabel),
4812 AST_FOR (tree, falseLabel),
4813 AST_FOR (tree, condLabel),
4814 AST_FOR (tree, initExpr),
4815 AST_FOR (tree, condExpr),
4816 AST_FOR (tree, loopExpr),
4817 tree->left), RESULT_TYPE_NONE);
4820 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4821 "node PARAM shouldn't be processed here");
4822 /* but in processParams() */
4825 TTYPE (tree) = TETYPE (tree) = NULL;
4829 /* some error found this tree will be killed */
4831 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4832 tree->opval.op = NULLOP;
4838 /*-----------------------------------------------------------------*/
4839 /* sizeofOp - processes size of operation */
4840 /*-----------------------------------------------------------------*/
4842 sizeofOp (sym_link * type)
4847 /* make sure the type is complete and sane */
4848 checkTypeSanity(type, "(sizeof)");
4850 /* get the size and convert it to character */
4851 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4852 if (!size && !IS_VOID(type))
4853 werror (E_SIZEOF_INCOMPLETE_TYPE);
4855 /* now convert into value */
4856 return constVal (buff);
4860 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4861 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4862 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4863 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4864 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4865 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4866 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4868 /*-----------------------------------------------------------------*/
4869 /* backPatchLabels - change and or not operators to flow control */
4870 /*-----------------------------------------------------------------*/
4872 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4878 /* while-loops insert a label between the IFX and the condition,
4879 therefore look behind the label too */
4880 if (tree->opval.op == LABEL &&
4882 IS_ANDORNOT (tree->right))
4884 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4888 if (!(IS_ANDORNOT (tree)))
4891 /* if this an and */
4894 static int localLbl = 0;
4897 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4898 localLabel = newSymbol (buffer, NestLevel);
4900 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4902 /* if left is already a IFX then just change the if true label in that */
4903 if (!IS_IFX (tree->left))
4904 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4906 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4907 /* right is a IFX then just join */
4908 if (IS_IFX (tree->right))
4909 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4911 tree->right = createLabel (localLabel, tree->right);
4912 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4914 return newNode (NULLOP, tree->left, tree->right);
4917 /* if this is an or operation */
4920 static int localLbl = 0;
4923 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4924 localLabel = newSymbol (buffer, NestLevel);
4926 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4928 /* if left is already a IFX then just change the if true label in that */
4929 if (!IS_IFX (tree->left))
4930 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4932 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4933 /* right is a IFX then just join */
4934 if (IS_IFX (tree->right))
4935 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4937 tree->right = createLabel (localLabel, tree->right);
4938 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4940 return newNode (NULLOP, tree->left, tree->right);
4946 /* call with exchanged labels */
4947 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4949 /* if left isn't already a IFX */
4950 if (!IS_IFX (tree->left))
4952 tree->left = newNode (IFX, tree->left, NULL);
4953 tree->left->trueLabel = falseLabel;
4954 tree->left->falseLabel = trueLabel;
4961 tree->trueLabel = trueLabel;
4962 tree->falseLabel = falseLabel;
4969 /*-----------------------------------------------------------------*/
4970 /* createBlock - create expression tree for block */
4971 /*-----------------------------------------------------------------*/
4973 createBlock (symbol * decl, ast * body)
4977 /* if the block has nothing */
4981 ex = newNode (BLOCK, NULL, body);
4982 ex->values.sym = decl;
4985 ex->filename = NULL;
4990 /*-----------------------------------------------------------------*/
4991 /* createLabel - creates the expression tree for labels */
4992 /*-----------------------------------------------------------------*/
4994 createLabel (symbol * label, ast * stmnt)
4997 char name[SDCC_NAME_MAX + 1];
5000 /* must create fresh symbol if the symbol name */
5001 /* exists in the symbol table, since there can */
5002 /* be a variable with the same name as the labl */
5003 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5004 (csym->level == label->level))
5005 label = newSymbol (label->name, label->level);
5007 /* change the name before putting it in add _ */
5008 SNPRINTF(name, sizeof(name), "%s", label->name);
5010 /* put the label in the LabelSymbol table */
5011 /* but first check if a label of the same */
5013 if ((csym = findSym (LabelTab, NULL, name)))
5014 werror (E_DUPLICATE_LABEL, label->name);
5016 addSym (LabelTab, label, name, label->level, 0, 0);
5020 label->key = labelKey++;
5021 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5022 rValue->filename = NULL;
5028 /*-----------------------------------------------------------------*/
5029 /* createCase - generates the parsetree for a case statement */
5030 /*-----------------------------------------------------------------*/
5032 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5034 char caseLbl[SDCC_NAME_MAX + 1];
5038 /* if the switch statement does not exist */
5039 /* then case is out of context */
5042 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5046 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5047 /* if not a constant then error */
5048 if (!IS_LITERAL (caseVal->ftype))
5050 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5054 /* if not a integer than error */
5055 if (!IS_INTEGRAL (caseVal->ftype))
5057 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5061 /* find the end of the switch values chain */
5062 if (!(val = swStat->values.switchVals.swVals))
5063 swStat->values.switchVals.swVals = caseVal->opval.val;
5066 /* also order the cases according to value */
5068 int cVal = (int) ulFromVal (caseVal->opval.val);
5069 while (val && (int) ulFromVal (val) < cVal)
5075 /* if we reached the end then */
5078 pval->next = caseVal->opval.val;
5080 else if ((int) ulFromVal (val) == cVal)
5082 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5088 /* we found a value greater than */
5089 /* the current value we must add this */
5090 /* before the value */
5091 caseVal->opval.val->next = val;
5093 /* if this was the first in chain */
5094 if (swStat->values.switchVals.swVals == val)
5095 swStat->values.switchVals.swVals =
5098 pval->next = caseVal->opval.val;
5103 /* create the case label */
5104 SNPRINTF(caseLbl, sizeof(caseLbl),
5106 swStat->values.switchVals.swNum,
5107 (int) ulFromVal (caseVal->opval.val));
5109 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5110 rexpr->filename = 0;
5115 /*-----------------------------------------------------------------*/
5116 /* createDefault - creates the parse tree for the default statement */
5117 /*-----------------------------------------------------------------*/
5119 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5121 char defLbl[SDCC_NAME_MAX + 1];
5123 /* if the switch statement does not exist */
5124 /* then case is out of context */
5127 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5131 if (swStat->values.switchVals.swDefault)
5133 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5138 /* turn on the default flag */
5139 swStat->values.switchVals.swDefault = 1;
5141 /* create the label */
5142 SNPRINTF (defLbl, sizeof(defLbl),
5143 "_default_%d", swStat->values.switchVals.swNum);
5144 return createLabel (newSymbol (defLbl, 0), stmnt);
5147 /*-----------------------------------------------------------------*/
5148 /* createIf - creates the parsetree for the if statement */
5149 /*-----------------------------------------------------------------*/
5151 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5153 static int Lblnum = 0;
5155 symbol *ifTrue, *ifFalse, *ifEnd;
5157 /* if neither exists */
5158 if (!elseBody && !ifBody) {
5159 // if there are no side effects (i++, j() etc)
5160 if (!hasSEFcalls(condAst)) {
5165 /* create the labels */
5166 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5167 ifFalse = newSymbol (buffer, NestLevel);
5168 /* if no else body then end == false */
5173 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5174 ifEnd = newSymbol (buffer, NestLevel);
5177 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5178 ifTrue = newSymbol (buffer, NestLevel);
5182 /* attach the ifTrue label to the top of it body */
5183 ifBody = createLabel (ifTrue, ifBody);
5184 /* attach a goto end to the ifBody if else is present */
5187 ifBody = newNode (NULLOP, ifBody,
5189 newAst_VALUE (symbolVal (ifEnd)),
5191 /* put the elseLabel on the else body */
5192 elseBody = createLabel (ifFalse, elseBody);
5193 /* out the end at the end of the body */
5194 elseBody = newNode (NULLOP,
5196 createLabel (ifEnd, NULL));
5200 ifBody = newNode (NULLOP, ifBody,
5201 createLabel (ifFalse, NULL));
5203 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5204 if (IS_IFX (condAst))
5207 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5209 return newNode (NULLOP, ifTree,
5210 newNode (NULLOP, ifBody, elseBody));
5214 /*-----------------------------------------------------------------*/
5215 /* createDo - creates parse tree for do */
5218 /* _docontinue_n: */
5219 /* condition_expression +-> trueLabel -> _dobody_n */
5221 /* +-> falseLabel-> _dobreak_n */
5223 /*-----------------------------------------------------------------*/
5225 createDo (symbol * trueLabel, symbol * continueLabel,
5226 symbol * falseLabel, ast * condAst, ast * doBody)
5231 /* if the body does not exist then it is simple */
5234 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5235 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5236 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5237 doTree->trueLabel = continueLabel;
5238 doTree->falseLabel = NULL;
5240 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5244 /* otherwise we have a body */
5245 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5247 /* attach the body label to the top */
5248 doBody = createLabel (trueLabel, doBody);
5249 /* attach the continue label to end of body */
5250 doBody = newNode (NULLOP, doBody,
5251 createLabel (continueLabel, NULL));
5253 /* now put the break label at the end */
5254 if (IS_IFX (condAst))
5257 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5259 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5261 /* putting it together */
5262 return newNode (NULLOP, doBody, doTree);
5265 /*-----------------------------------------------------------------*/
5266 /* createFor - creates parse tree for 'for' statement */
5269 /* condExpr +-> trueLabel -> _forbody_n */
5271 /* +-> falseLabel-> _forbreak_n */
5274 /* _forcontinue_n: */
5276 /* goto _forcond_n ; */
5278 /*-----------------------------------------------------------------*/
5280 createFor (symbol * trueLabel, symbol * continueLabel,
5281 symbol * falseLabel, symbol * condLabel,
5282 ast * initExpr, ast * condExpr, ast * loopExpr,
5287 /* if loopexpression not present then we can generate it */
5288 /* the same way as a while */
5290 return newNode (NULLOP, initExpr,
5291 createWhile (trueLabel, continueLabel,
5292 falseLabel, condExpr, forBody));
5293 /* vanilla for statement */
5294 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5296 if (condExpr && !IS_IFX (condExpr))
5297 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5300 /* attach condition label to condition */
5301 condExpr = createLabel (condLabel, condExpr);
5303 /* attach body label to body */
5304 forBody = createLabel (trueLabel, forBody);
5306 /* attach continue to forLoop expression & attach */
5307 /* goto the forcond @ and of loopExpression */
5308 loopExpr = createLabel (continueLabel,
5312 newAst_VALUE (symbolVal (condLabel)),
5314 /* now start putting them together */
5315 forTree = newNode (NULLOP, initExpr, condExpr);
5316 forTree = newNode (NULLOP, forTree, forBody);
5317 forTree = newNode (NULLOP, forTree, loopExpr);
5318 /* finally add the break label */
5319 forTree = newNode (NULLOP, forTree,
5320 createLabel (falseLabel, NULL));
5324 /*-----------------------------------------------------------------*/
5325 /* createWhile - creates parse tree for while statement */
5326 /* the while statement will be created as follows */
5328 /* _while_continue_n: */
5329 /* condition_expression +-> trueLabel -> _while_boby_n */
5331 /* +-> falseLabel -> _while_break_n */
5332 /* _while_body_n: */
5334 /* goto _while_continue_n */
5335 /* _while_break_n: */
5336 /*-----------------------------------------------------------------*/
5338 createWhile (symbol * trueLabel, symbol * continueLabel,
5339 symbol * falseLabel, ast * condExpr, ast * whileBody)
5343 /* put the continue label */
5344 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5345 condExpr = createLabel (continueLabel, condExpr);
5346 condExpr->filename = NULL;
5347 condExpr->lineno = 0;
5349 /* put the body label in front of the body */
5350 whileBody = createLabel (trueLabel, whileBody);
5351 whileBody->filename = NULL;
5352 whileBody->lineno = 0;
5353 /* put a jump to continue at the end of the body */
5354 /* and put break label at the end of the body */
5355 whileBody = newNode (NULLOP,
5358 newAst_VALUE (symbolVal (continueLabel)),
5359 createLabel (falseLabel, NULL)));
5361 /* put it all together */
5362 if (IS_IFX (condExpr))
5363 whileTree = condExpr;
5366 whileTree = newNode (IFX, condExpr, NULL);
5367 /* put the true & false labels in place */
5368 whileTree->trueLabel = trueLabel;
5369 whileTree->falseLabel = falseLabel;
5372 return newNode (NULLOP, whileTree, whileBody);
5375 /*-----------------------------------------------------------------*/
5376 /* isShiftRightLitVal _BitAndLitVal - helper function */
5377 /*-----------------------------------------------------------------*/
5379 isShiftRightLitVal_BitAndLitVal (ast * tree)
5381 /* if this is not a bit and */
5382 if (!IS_BITAND (tree))
5385 /* will look for tree of the form
5386 ( expr >> litval2) & litval1 */
5387 if (!IS_AST_LIT_VALUE (tree->right))
5390 if (!IS_RIGHT_OP (tree->left))
5393 if (!IS_AST_LIT_VALUE (tree->left->right))
5396 return tree->left->left;
5399 /*-----------------------------------------------------------------*/
5400 /* isBitAndPowOf2 - helper function */
5401 /*-----------------------------------------------------------------*/
5403 isBitAndPow2 (ast * tree)
5405 /* if this is not a bit and */
5406 if (!IS_BITAND (tree))
5409 /* will look for tree of the form
5410 ( expr & (1 << litval) */
5411 if (!IS_AST_LIT_VALUE (tree->right))
5414 return powof2 (AST_ULONG_VALUE (tree->right));
5417 /*-----------------------------------------------------------------*/
5418 /* optimizeGetHbit - get highest order bit of the expression */
5419 /*-----------------------------------------------------------------*/
5421 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5426 expr = isShiftRightLitVal_BitAndLitVal(tree);
5429 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5430 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5431 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5434 if (!expr && (resultType == RESULT_TYPE_BIT))
5437 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5443 /* make sure the port supports GETHBIT */
5444 if (port->hasExtBitOp
5445 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5448 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5451 /*-----------------------------------------------------------------*/
5452 /* optimizeGetAbit - get a single bit of the expression */
5453 /*-----------------------------------------------------------------*/
5455 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5460 expr = isShiftRightLitVal_BitAndLitVal(tree);
5463 if (AST_ULONG_VALUE (tree->right) != 1)
5465 count = tree->left->right;
5467 if (!expr && (resultType == RESULT_TYPE_BIT))
5469 int p2 = isBitAndPow2 (tree);
5473 count = newAst_VALUE (valueFromLit (p2));
5479 /* make sure the port supports GETABIT */
5480 if (port->hasExtBitOp
5481 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5484 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5488 /*-----------------------------------------------------------------*/
5489 /* optimizeGetByte - get a byte of the expression */
5490 /*-----------------------------------------------------------------*/
5492 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5498 expr = isShiftRightLitVal_BitAndLitVal(tree);
5501 i = AST_ULONG_VALUE (tree->left->right);
5502 count = tree->left->right;
5503 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5506 if (!expr && resultType == RESULT_TYPE_CHAR)
5508 /* if this is a right shift over a multiple of 8 */
5509 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5511 i = AST_ULONG_VALUE (tree->right);
5512 count = tree->right;
5516 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5519 /* make sure the port supports GETBYTE */
5520 if (port->hasExtBitOp
5521 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5524 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5527 /*-----------------------------------------------------------------*/
5528 /* optimizeGetWord - get two bytes of the expression */
5529 /*-----------------------------------------------------------------*/
5531 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5537 expr = isShiftRightLitVal_BitAndLitVal(tree);
5540 i = AST_ULONG_VALUE (tree->left->right);
5541 count = tree->left->right;
5542 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5545 if (!expr && resultType == RESULT_TYPE_INT)
5547 /* if this is a right shift over a multiple of 8 */
5548 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5550 i = AST_ULONG_VALUE (tree->right);
5551 count = tree->right;
5555 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5558 /* make sure the port supports GETWORD */
5559 if (port->hasExtBitOp
5560 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5563 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5566 /*-----------------------------------------------------------------*/
5567 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5568 /*-----------------------------------------------------------------*/
5570 optimizeRRCRLC (ast * root)
5572 /* will look for trees of the form
5573 (?expr << 1) | (?expr >> 7) or
5574 (?expr >> 7) | (?expr << 1) will make that
5575 into a RLC : operation ..
5577 (?expr >> 1) | (?expr << 7) or
5578 (?expr << 7) | (?expr >> 1) will make that
5579 into a RRC operation
5580 note : by 7 I mean (number of bits required to hold the
5582 /* if the root operation is not a | operation then not */
5583 if (!IS_BITOR (root))
5586 /* I have to think of a better way to match patterns this sucks */
5587 /* that aside let's start looking for the first case : I use a
5588 negative check a lot to improve the efficiency */
5589 /* (?expr << 1) | (?expr >> 7) */
5590 if (IS_LEFT_OP (root->left) &&
5591 IS_RIGHT_OP (root->right))
5594 if (!SPEC_USIGN (TETYPE (root->left->left)))
5597 if (!IS_AST_LIT_VALUE (root->left->right) ||
5598 !IS_AST_LIT_VALUE (root->right->right))
5601 /* make sure it is the same expression */
5602 if (!isAstEqual (root->left->left,
5606 if (AST_ULONG_VALUE (root->left->right) != 1)
5609 if (AST_ULONG_VALUE (root->right->right) !=
5610 (getSize (TTYPE (root->left->left)) * 8 - 1))
5613 /* make sure the port supports RLC */
5614 if (port->hasExtBitOp
5615 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5618 /* whew got the first case : create the AST */
5619 return newNode (RLC, root->left->left, NULL);
5623 /* check for second case */
5624 /* (?expr >> 7) | (?expr << 1) */
5625 if (IS_LEFT_OP (root->right) &&
5626 IS_RIGHT_OP (root->left))
5629 if (!SPEC_USIGN (TETYPE (root->left->left)))
5632 if (!IS_AST_LIT_VALUE (root->left->right) ||
5633 !IS_AST_LIT_VALUE (root->right->right))
5636 /* make sure it is the same symbol */
5637 if (!isAstEqual (root->left->left,
5641 if (AST_ULONG_VALUE (root->right->right) != 1)
5644 if (AST_ULONG_VALUE (root->left->right) !=
5645 (getSize (TTYPE (root->left->left)) * 8 - 1))
5648 /* make sure the port supports RLC */
5649 if (port->hasExtBitOp
5650 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5653 /* whew got the first case : create the AST */
5654 return newNode (RLC, root->left->left, NULL);
5659 /* third case for RRC */
5660 /* (?symbol >> 1) | (?symbol << 7) */
5661 if (IS_LEFT_OP (root->right) &&
5662 IS_RIGHT_OP (root->left))
5665 if (!SPEC_USIGN (TETYPE (root->left->left)))
5668 if (!IS_AST_LIT_VALUE (root->left->right) ||
5669 !IS_AST_LIT_VALUE (root->right->right))
5672 /* make sure it is the same symbol */
5673 if (!isAstEqual (root->left->left,
5677 if (AST_ULONG_VALUE (root->left->right) != 1)
5680 if (AST_ULONG_VALUE (root->right->right) !=
5681 (getSize (TTYPE (root->left->left)) * 8 - 1))
5684 /* make sure the port supports RRC */
5685 if (port->hasExtBitOp
5686 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5689 /* whew got the first case : create the AST */
5690 return newNode (RRC, root->left->left, NULL);
5694 /* fourth and last case for now */
5695 /* (?symbol << 7) | (?symbol >> 1) */
5696 if (IS_RIGHT_OP (root->right) &&
5697 IS_LEFT_OP (root->left))
5700 if (!SPEC_USIGN (TETYPE (root->left->left)))
5703 if (!IS_AST_LIT_VALUE (root->left->right) ||
5704 !IS_AST_LIT_VALUE (root->right->right))
5707 /* make sure it is the same symbol */
5708 if (!isAstEqual (root->left->left,
5712 if (AST_ULONG_VALUE (root->right->right) != 1)
5715 if (AST_ULONG_VALUE (root->left->right) !=
5716 (getSize (TTYPE (root->left->left)) * 8 - 1))
5719 /* make sure the port supports RRC */
5720 if (port->hasExtBitOp
5721 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5724 /* whew got the first case : create the AST */
5725 return newNode (RRC, root->left->left, NULL);
5729 /* not found return root */
5733 /*-----------------------------------------------------------------*/
5734 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5735 /*-----------------------------------------------------------------*/
5737 optimizeSWAP (ast * root)
5739 /* will look for trees of the form
5740 (?expr << 4) | (?expr >> 4) or
5741 (?expr >> 4) | (?expr << 4) will make that
5742 into a SWAP : operation ..
5743 note : by 4 I mean (number of bits required to hold the
5745 /* if the root operation is not a | operation then not */
5746 if (!IS_BITOR (root))
5749 /* (?expr << 4) | (?expr >> 4) */
5750 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5751 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5754 if (!SPEC_USIGN (TETYPE (root->left->left)))
5757 if (!IS_AST_LIT_VALUE (root->left->right) ||
5758 !IS_AST_LIT_VALUE (root->right->right))
5761 /* make sure it is the same expression */
5762 if (!isAstEqual (root->left->left,
5766 if (AST_ULONG_VALUE (root->left->right) !=
5767 (getSize (TTYPE (root->left->left)) * 4))
5770 if (AST_ULONG_VALUE (root->right->right) !=
5771 (getSize (TTYPE (root->left->left)) * 4))
5774 /* make sure the port supports SWAP */
5775 if (port->hasExtBitOp
5776 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5779 /* found it : create the AST */
5780 return newNode (SWAP, root->left->left, NULL);
5784 /* not found return root */
5788 /*-----------------------------------------------------------------*/
5789 /* optimizeCompare - optimizes compares for bit variables */
5790 /*-----------------------------------------------------------------*/
5792 optimizeCompare (ast * root)
5794 ast *optExpr = NULL;
5797 unsigned int litValue;
5799 /* if nothing then return nothing */
5803 /* if not a compare op then do leaves */
5804 if (!IS_COMPARE_OP (root))
5806 root->left = optimizeCompare (root->left);
5807 root->right = optimizeCompare (root->right);
5811 /* if left & right are the same then depending
5812 of the operation do */
5813 if (isAstEqual (root->left, root->right))
5815 switch (root->opval.op)
5820 optExpr = newAst_VALUE (constCharVal (0));
5825 optExpr = newAst_VALUE (constCharVal (1));
5829 return decorateType (optExpr, RESULT_TYPE_NONE);
5832 vleft = (root->left->type == EX_VALUE ?
5833 root->left->opval.val : NULL);
5835 vright = (root->right->type == EX_VALUE ?
5836 root->right->opval.val : NULL);
5838 /* if left is a BITVAR in BITSPACE */
5839 /* and right is a LITERAL then */
5840 /* optimize else do nothing */
5841 if (vleft && vright &&
5842 IS_BITVAR (vleft->etype) &&
5843 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5844 IS_LITERAL (vright->etype))
5847 /* if right side > 1 then comparison may never succeed */
5848 if ((litValue = (int) ulFromVal (vright)) > 1)
5850 werror (W_BAD_COMPARE);
5856 switch (root->opval.op)
5858 case '>': /* bit value greater than 1 cannot be */
5859 werror (W_BAD_COMPARE);
5863 case '<': /* bit value < 1 means 0 */
5865 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5868 case LE_OP: /* bit value <= 1 means no check */
5869 optExpr = newAst_VALUE (vright);
5872 case GE_OP: /* bit value >= 1 means only check for = */
5874 optExpr = newAst_VALUE (vleft);
5879 { /* literal is zero */
5880 switch (root->opval.op)
5882 case '<': /* bit value < 0 cannot be */
5883 werror (W_BAD_COMPARE);
5887 case '>': /* bit value > 0 means 1 */
5889 optExpr = newAst_VALUE (vleft);
5892 case LE_OP: /* bit value <= 0 means no check */
5893 case GE_OP: /* bit value >= 0 means no check */
5894 werror (W_BAD_COMPARE);
5898 case EQ_OP: /* bit == 0 means ! of bit */
5899 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5903 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5904 } /* end-of-if of BITVAR */
5910 /*-----------------------------------------------------------------*/
5911 /* addSymToBlock : adds the symbol to the first block we find */
5912 /*-----------------------------------------------------------------*/
5914 addSymToBlock (symbol * sym, ast * tree)
5916 /* reached end of tree or a leaf */
5917 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5921 if (IS_AST_OP (tree) &&
5922 tree->opval.op == BLOCK)
5925 symbol *lsym = copySymbol (sym);
5927 lsym->next = AST_VALUES (tree, sym);
5928 AST_VALUES (tree, sym) = lsym;
5932 addSymToBlock (sym, tree->left);
5933 addSymToBlock (sym, tree->right);
5936 /*-----------------------------------------------------------------*/
5937 /* processRegParms - do processing for register parameters */
5938 /*-----------------------------------------------------------------*/
5940 processRegParms (value * args, ast * body)
5944 if (IS_REGPARM (args->etype))
5945 addSymToBlock (args->sym, body);
5950 /*-----------------------------------------------------------------*/
5951 /* resetParmKey - resets the operandkeys for the symbols */
5952 /*-----------------------------------------------------------------*/
5953 DEFSETFUNC (resetParmKey)
5966 /*------------------------------------------------------------------*/
5967 /* fixupInlineLabel - change a label in an inlined function so that */
5968 /* it is always unique no matter how many times */
5969 /* the function is inlined. */
5970 /*------------------------------------------------------------------*/
5972 fixupInlineLabel (symbol * sym)
5974 char name[SDCC_NAME_MAX + 1];
5976 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5977 strcpy (sym->name, name);
5981 /*------------------------------------------------------------------*/
5982 /* copyAstLoc - copy location information (file, line, block, etc.) */
5983 /* from one ast node to another */
5984 /*------------------------------------------------------------------*/
5986 copyAstLoc (ast * dest, ast * src)
5988 dest->filename = src->filename;
5989 dest->lineno = src->lineno;
5990 dest->level = src->level;
5991 dest->block = src->block;
5992 dest->seqPoint = src->seqPoint;
5997 /*-----------------------------------------------------------------*/
5998 /* fixupInline - perform various fixups on an inline function tree */
5999 /* to take into account that it is no longer a */
6000 /* stand-alone function. */
6001 /*-----------------------------------------------------------------*/
6003 fixupInline (ast * tree, int level)
6005 tree->block = currBlockno;
6007 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6014 /* Add any declared variables back into the symbol table */
6015 decls = tree->values.sym;
6018 decls->level = level;
6019 decls->block = currBlockno;
6020 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6021 decls = decls->next;
6025 tree->level = level;
6027 /* Update symbols */
6028 if (IS_AST_VALUE (tree) &&
6029 tree->opval.val->sym)
6031 symbol * sym = tree->opval.val->sym;
6034 sym->block = currBlockno;
6037 SYM_SPIL_LOC (sym) = NULL;
6040 /* If the symbol is a label, we need to renumber it */
6042 fixupInlineLabel (sym);
6045 /* Update IFX target labels */
6046 if (tree->type == EX_OP && tree->opval.op == IFX)
6048 if (tree->trueLabel)
6049 fixupInlineLabel (tree->trueLabel);
6050 if (tree->falseLabel)
6051 fixupInlineLabel (tree->falseLabel);
6054 /* Replace RETURN with optional assignment and a GOTO to the end */
6055 /* of the inlined function */
6056 if (tree->type == EX_OP && tree->opval.op == RETURN)
6058 ast * assignTree = NULL;
6061 if (inlineState.retsym && tree->right)
6063 assignTree = newNode ('=',
6064 newAst_VALUE (symbolVal (inlineState.retsym)),
6066 copyAstLoc (assignTree, tree);
6069 gotoTree = newNode (GOTO,
6070 newAst_VALUE (symbolVal (inlineState.retlab)),
6072 copyAstLoc (gotoTree, tree);
6074 tree->opval.op = NULLOP;
6075 tree->left = assignTree;
6076 tree->right = gotoTree;
6079 /* Update any children */
6081 fixupInline (tree->left, level);
6083 fixupInline (tree->right, level);
6085 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6087 symbol * label = tree->left->opval.val->sym;
6089 label->key = labelKey++;
6090 /* Add this label back into the symbol table */
6091 addSym (LabelTab, label, label->name, label->level, 0, 0);
6095 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6101 /*-----------------------------------------------------------------*/
6102 /* inlineAddDecl - add a variable declaration to an ast block. It */
6103 /* is also added to the symbol table if addSymTab */
6105 /*-----------------------------------------------------------------*/
6107 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6110 SYM_SPIL_LOC (sym) = NULL;
6114 symbol **decl = &(block->values.sym);
6116 sym->level = block->level;
6117 sym->block = block->block;
6121 if (strcmp ((*decl)->name, sym->name) == 0)
6123 decl = &( (*decl)->next );
6129 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6135 /*-----------------------------------------------------------------*/
6136 /* inlineTempVar - create a temporary variable for inlining */
6137 /*-----------------------------------------------------------------*/
6139 inlineTempVar (sym_link * type, int level)
6143 sym = newSymbol (genSymName(level), level );
6144 sym->type = copyLinkChain (type);
6145 sym->etype = getSpec(sym->type);
6146 SPEC_SCLS (sym->etype) = S_AUTO;
6147 SPEC_OCLS (sym->etype) = NULL;
6148 SPEC_EXTR (sym->etype) = 0;
6149 SPEC_STAT (sym->etype) = 0;
6150 if IS_SPEC (sym->type)
6151 SPEC_VOLATILE (sym->type) = 0;
6153 DCL_PTR_VOLATILE (sym->type) = 0;
6154 SPEC_ABSA (sym->etype) = 0;
6160 /*-----------------------------------------------------------------*/
6161 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6162 /*-----------------------------------------------------------------*/
6164 inlineFindParmRecurse (ast * parms, int *index)
6169 if (parms->type == EX_OP && parms->opval.op == PARAM)
6173 p=inlineFindParmRecurse (parms->left, index);
6176 p=inlineFindParmRecurse (parms->right, index);
6187 /*-----------------------------------------------------------------*/
6188 /* inlineFindParm - search an ast tree of parameters to find one */
6189 /* at a particular index (0=first parameter). */
6190 /* Returns NULL if not found. */
6191 /*-----------------------------------------------------------------*/
6193 inlineFindParm (ast * parms, int index)
6195 return inlineFindParmRecurse (parms, &index);
6198 /*-----------------------------------------------------------------*/
6199 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6200 /*-----------------------------------------------------------------*/
6202 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6209 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6210 if (tempBlockno > maxBlockno)
6211 maxBlockno = tempBlockno;
6213 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6214 if (tempBlockno > maxBlockno)
6215 maxBlockno = tempBlockno;
6217 if (tree->block > maxBlockno)
6218 maxBlockno = tree->block;
6225 /*-----------------------------------------------------------------*/
6226 /* expandInlineFuncs - replace calls to inline functions with the */
6227 /* function itself */
6228 /*-----------------------------------------------------------------*/
6230 expandInlineFuncs (ast * tree, ast * block)
6232 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6233 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6235 symbol * func = tree->left->opval.val->sym;
6238 /* The symbol is probably not bound yet, so find the real one */
6239 csym = findSymWithLevel (SymbolTab, func);
6243 /* Is this an inline function that we can inline? */
6244 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6246 symbol * retsym = NULL;
6254 /* Generate a label for the inlined function to branch to */
6255 /* in case it contains a return statement */
6256 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6259 inlineState.retlab = retlab;
6261 /* Build the subtree for the inlined function in the form: */
6262 /* { //inlinetree block */
6263 /* { //inlinetree2 block */
6264 /* inline_function_code; */
6268 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6269 copyAstLoc (temptree, tree);
6270 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6271 copyAstLoc (temptree, tree);
6272 temptree = newNode (BLOCK, NULL, temptree);
6273 copyAstLoc (temptree, tree);
6274 inlinetree2 = temptree;
6275 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6276 copyAstLoc (inlinetree, tree);
6278 /* To pass parameters to the inlined function, we need some */
6279 /* intermediate variables. This avoids scoping problems */
6280 /* when the parameter declaration names are used differently */
6281 /* during the function call. For example, a function */
6282 /* declared as func(int x, int y) but called as func(y,x). */
6283 /* { //inlinetree block */
6284 /* type1 temparg1; */
6286 /* typen tempargn; */
6287 /* temparg1 = argument1; */
6289 /* tempargn = argumentn; */
6290 /* { //inlinetree2 block */
6294 /* param1 = temparg1; */
6296 /* paramn = tempargn; */
6297 /* inline_function_code; */
6301 args = FUNC_ARGS (func->type);
6308 symbol * parm = copySymbol (args->sym);
6310 temparg = inlineTempVar (args->sym->type, tree->level+1);
6311 inlineAddDecl (temparg, inlinetree, FALSE);
6313 passedarg = inlineFindParm (tree->right, argIndex);
6314 assigntree = newNode ('=',
6315 newAst_VALUE (symbolVal (temparg)),
6317 inlinetree->right = newNode (NULLOP,
6321 inlineAddDecl (parm, inlinetree2, FALSE);
6324 assigntree = newNode ('=',
6325 newAst_VALUE (symbolVal (parm)),
6326 newAst_VALUE (symbolVal (temparg)));
6327 inlinetree2->right = newNode (NULLOP,
6329 inlinetree2->right);
6336 /* Handle the return type */
6337 if (!IS_VOID (func->type->next))
6339 /* Create a temporary symbol to hold the return value and */
6340 /* join it with the inlined function using the comma */
6341 /* operator. The fixupInline function will take care of */
6342 /* changing return statements into assignments to retsym. */
6343 /* (parameter passing and return label omitted for clarity) */
6344 /* rettype retsym; */
6346 /* {{inline_function_code}}, retsym */
6348 retsym = inlineTempVar (func->type->next, tree->level);
6349 inlineAddDecl (retsym, block, TRUE);
6351 tree->opval.op = ',';
6352 tree->left = inlinetree;
6353 tree->right = newAst_VALUE (symbolVal (retsym));
6357 tree->opval.op = NULLOP;
6359 tree->right = inlinetree;
6361 inlineState.retsym = retsym;
6363 /* Renumber the various internal counters on the inlined */
6364 /* function's tree nodes and symbols. Add the inlined */
6365 /* function's local variables to the appropriate scope(s). */
6366 /* Convert inlined return statements to an assignment to */
6367 /* retsym (if needed) and a goto retlab. */
6368 fixupInline (inlinetree, inlinetree->level);
6369 inlineState.count++;
6374 /* Recursively continue to search for functions to inline. */
6375 if (IS_AST_OP (tree))
6377 if (tree->opval.op == BLOCK)
6381 expandInlineFuncs (tree->left, block);
6383 expandInlineFuncs (tree->right, block);
6388 /*-----------------------------------------------------------------*/
6389 /* createFunction - This is the key node that calls the iCode for */
6390 /* generating the code for a function. Note code */
6391 /* is generated function by function, later when */
6392 /* add inter-procedural analysis this will change */
6393 /*-----------------------------------------------------------------*/
6395 createFunction (symbol * name, ast * body)
6401 iCode *piCode = NULL;
6404 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6405 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6407 /* if check function return 0 then some problem */
6408 if (checkFunction (name, NULL) == 0)
6411 /* create a dummy block if none exists */
6413 body = newNode (BLOCK, NULL, NULL);
6417 /* check if the function name already in the symbol table */
6418 if ((csym = findSym (SymbolTab, NULL, name->name)))
6421 /* special case for compiler defined functions
6422 we need to add the name to the publics list : this
6423 actually means we are now compiling the compiler
6427 addSet (&publics, name);
6432 addSymChain (&name);
6433 allocVariables (name);
6435 name->lastLine = lexLineno;
6438 /* set the stack pointer */
6439 stackPtr = -port->stack.direction * port->stack.call_overhead;
6442 if (IFFUNC_ISISR (name->type))
6443 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6445 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6447 if (options.useXstack)
6448 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6450 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6453 fetype = getSpec (name->type); /* get the specifier for the function */
6454 /* if this is a reentrant function then */
6455 if (IFFUNC_ISREENT (name->type))
6458 inlineState.count = 0;
6459 savedBlockno = currBlockno;
6460 currBlockno = inlineFindMaxBlockno (body, 0);
6461 expandInlineFuncs (body, NULL);
6462 currBlockno = savedBlockno;
6464 if (FUNC_ISINLINE (name->type))
6465 name->funcTree = copyAst (body);
6467 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6469 /* do processing for parameters that are passed in registers */
6470 processRegParms (FUNC_ARGS(name->type), body);
6472 /* set the stack pointer */
6476 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6478 /* allocate & autoinit the block variables */
6479 processBlockVars (body, &stack, ALLOCATE);
6481 /* name needs to be mangled */
6482 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6484 body = resolveSymbols (body); /* resolve the symbols */
6485 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6487 /* save the stack information */
6488 if (options.useXstack)
6489 name->xstack = SPEC_STAK (fetype) = stack;
6491 name->stack = SPEC_STAK (fetype) = stack;
6493 ex = newAst_VALUE (symbolVal (name)); /* create name */
6494 ex = newNode (FUNCTION, ex, body);
6495 ex->values.args = FUNC_ARGS(name->type);
6497 if (options.dump_tree)
6502 /* Do not generate code for inline functions unless extern also. */
6504 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6507 /* Temporary hack: always generate code for static inline functions. */
6508 /* Ideally static inline functions should only be generated if needed. */
6509 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6513 /* create the node & generate intermediate code */
6515 codeOutBuf = &code->oBuf;
6516 piCode = iCodeFromAst (ex);
6517 name->generated = 1;
6522 eBBlockFromiCode (piCode);
6524 /* if there are any statics then do them */
6527 GcurMemmap = statsg;
6528 codeOutBuf = &statsg->oBuf;
6529 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6535 /* dealloc the block variables */
6536 processBlockVars (body, &stack, DEALLOCATE);
6537 outputDebugStackSymbols();
6538 /* deallocate paramaters */
6539 deallocParms (FUNC_ARGS(name->type));
6541 if (IFFUNC_ISREENT (name->type))
6544 /* we are done freeup memory & cleanup */
6546 if (port->reset_labelKey) labelKey = 1;
6548 FUNC_HASBODY(name->type) = 1;
6549 addSet (&operKeyReset, name);
6550 applyToSet (operKeyReset, resetParmKey);
6555 cleanUpLevel (LabelTab, 0);
6556 cleanUpBlock (StructTab, 1);
6557 cleanUpBlock (TypedefTab, 1);
6559 xstack->syms = NULL;
6560 istack->syms = NULL;
6565 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6566 /*-----------------------------------------------------------------*/
6567 /* ast_print : prints the ast (for debugging purposes) */
6568 /*-----------------------------------------------------------------*/
6570 void ast_print (ast * tree, FILE *outfile, int indent)
6575 /* can print only decorated trees */
6576 if (!tree->decorated) return;
6578 /* if any child is an error | this one is an error do nothing */
6579 if (tree->isError ||
6580 (tree->left && tree->left->isError) ||
6581 (tree->right && tree->right->isError)) {
6582 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6586 /* print the line */
6587 /* if not block & function */
6588 if (tree->type == EX_OP &&
6589 (tree->opval.op != FUNCTION &&
6590 tree->opval.op != BLOCK &&
6591 tree->opval.op != NULLOP)) {
6594 if (tree->opval.op == FUNCTION) {
6596 value *args=FUNC_ARGS(tree->left->opval.val->type);
6597 fprintf(outfile,"FUNCTION (%s=%p) type (",
6598 tree->left->opval.val->name, tree);
6599 printTypeChain (tree->left->opval.val->type->next,outfile);
6600 fprintf(outfile,") args (");
6603 fprintf (outfile, ", ");
6605 printTypeChain (args ? args->type : NULL, outfile);
6607 args= args ? args->next : NULL;
6609 fprintf(outfile,")\n");
6610 ast_print(tree->left,outfile,indent);
6611 ast_print(tree->right,outfile,indent);
6614 if (tree->opval.op == BLOCK) {
6615 symbol *decls = tree->values.sym;
6616 INDENT(indent,outfile);
6617 fprintf(outfile,"{\n");
6619 INDENT(indent+2,outfile);
6620 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6621 decls->name, decls);
6622 printTypeChain(decls->type,outfile);
6623 fprintf(outfile,")\n");
6625 decls = decls->next;
6627 ast_print(tree->right,outfile,indent+2);
6628 INDENT(indent,outfile);
6629 fprintf(outfile,"}\n");
6632 if (tree->opval.op == NULLOP) {
6633 ast_print(tree->left,outfile,indent);
6634 ast_print(tree->right,outfile,indent);
6637 INDENT(indent,outfile);
6639 /*------------------------------------------------------------------*/
6640 /*----------------------------*/
6641 /* leaf has been reached */
6642 /*----------------------------*/
6643 /* if this is of type value */
6644 /* just get the type */
6645 if (tree->type == EX_VALUE) {
6647 if (IS_LITERAL (tree->opval.val->etype)) {
6648 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6649 if (SPEC_USIGN (tree->opval.val->etype))
6650 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6652 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6653 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6654 floatFromVal(tree->opval.val));
6655 } else if (tree->opval.val->sym) {
6656 /* if the undefined flag is set then give error message */
6657 if (tree->opval.val->sym->undefined) {
6658 fprintf(outfile,"UNDEFINED SYMBOL ");
6660 fprintf(outfile,"SYMBOL ");
6662 fprintf(outfile,"(%s=%p @ %p)",
6663 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6666 fprintf(outfile," type (");
6667 printTypeChain(tree->ftype,outfile);
6668 fprintf(outfile,")\n");
6670 fprintf(outfile,"\n");
6675 /* if type link for the case of cast */
6676 if (tree->type == EX_LINK) {
6677 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6678 printTypeChain(tree->opval.lnk,outfile);
6679 fprintf(outfile,")\n");
6684 /* depending on type of operator do */
6686 switch (tree->opval.op) {
6687 /*------------------------------------------------------------------*/
6688 /*----------------------------*/
6690 /*----------------------------*/
6692 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6693 printTypeChain(tree->ftype,outfile);
6694 fprintf(outfile,")\n");
6695 ast_print(tree->left,outfile,indent+2);
6696 ast_print(tree->right,outfile,indent+2);
6699 /*------------------------------------------------------------------*/
6700 /*----------------------------*/
6702 /*----------------------------*/
6704 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6705 printTypeChain(tree->ftype,outfile);
6706 fprintf(outfile,")\n");
6707 ast_print(tree->left,outfile,indent+2);
6708 ast_print(tree->right,outfile,indent+2);
6711 /*------------------------------------------------------------------*/
6712 /*----------------------------*/
6713 /* struct/union pointer */
6714 /*----------------------------*/
6716 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6717 printTypeChain(tree->ftype,outfile);
6718 fprintf(outfile,")\n");
6719 ast_print(tree->left,outfile,indent+2);
6720 ast_print(tree->right,outfile,indent+2);
6723 /*------------------------------------------------------------------*/
6724 /*----------------------------*/
6725 /* ++/-- operation */
6726 /*----------------------------*/
6729 fprintf(outfile,"post-");
6731 fprintf(outfile,"pre-");
6732 fprintf(outfile,"INC_OP (%p) type (",tree);
6733 printTypeChain(tree->ftype,outfile);
6734 fprintf(outfile,")\n");
6735 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6736 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6741 fprintf(outfile,"post-");
6743 fprintf(outfile,"pre-");
6744 fprintf(outfile,"DEC_OP (%p) type (",tree);
6745 printTypeChain(tree->ftype,outfile);
6746 fprintf(outfile,")\n");
6747 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6748 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6751 /*------------------------------------------------------------------*/
6752 /*----------------------------*/
6754 /*----------------------------*/
6757 fprintf(outfile,"& (%p) type (",tree);
6758 printTypeChain(tree->ftype,outfile);
6759 fprintf(outfile,")\n");
6760 ast_print(tree->left,outfile,indent+2);
6761 ast_print(tree->right,outfile,indent+2);
6763 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6764 printTypeChain(tree->ftype,outfile);
6765 fprintf(outfile,")\n");
6766 ast_print(tree->left,outfile,indent+2);
6767 ast_print(tree->right,outfile,indent+2);
6770 /*----------------------------*/
6772 /*----------------------------*/
6774 fprintf(outfile,"OR (%p) type (",tree);
6775 printTypeChain(tree->ftype,outfile);
6776 fprintf(outfile,")\n");
6777 ast_print(tree->left,outfile,indent+2);
6778 ast_print(tree->right,outfile,indent+2);
6780 /*------------------------------------------------------------------*/
6781 /*----------------------------*/
6783 /*----------------------------*/
6785 fprintf(outfile,"XOR (%p) type (",tree);
6786 printTypeChain(tree->ftype,outfile);
6787 fprintf(outfile,")\n");
6788 ast_print(tree->left,outfile,indent+2);
6789 ast_print(tree->right,outfile,indent+2);
6792 /*------------------------------------------------------------------*/
6793 /*----------------------------*/
6795 /*----------------------------*/
6797 fprintf(outfile,"DIV (%p) type (",tree);
6798 printTypeChain(tree->ftype,outfile);
6799 fprintf(outfile,")\n");
6800 ast_print(tree->left,outfile,indent+2);
6801 ast_print(tree->right,outfile,indent+2);
6803 /*------------------------------------------------------------------*/
6804 /*----------------------------*/
6806 /*----------------------------*/
6808 fprintf(outfile,"MOD (%p) type (",tree);
6809 printTypeChain(tree->ftype,outfile);
6810 fprintf(outfile,")\n");
6811 ast_print(tree->left,outfile,indent+2);
6812 ast_print(tree->right,outfile,indent+2);
6815 /*------------------------------------------------------------------*/
6816 /*----------------------------*/
6817 /* address dereference */
6818 /*----------------------------*/
6819 case '*': /* can be unary : if right is null then unary operation */
6821 fprintf(outfile,"DEREF (%p) type (",tree);
6822 printTypeChain(tree->ftype,outfile);
6823 fprintf(outfile,")\n");
6824 ast_print(tree->left,outfile,indent+2);
6827 /*------------------------------------------------------------------*/
6828 /*----------------------------*/
6829 /* multiplication */
6830 /*----------------------------*/
6831 fprintf(outfile,"MULT (%p) type (",tree);
6832 printTypeChain(tree->ftype,outfile);
6833 fprintf(outfile,")\n");
6834 ast_print(tree->left,outfile,indent+2);
6835 ast_print(tree->right,outfile,indent+2);
6839 /*------------------------------------------------------------------*/
6840 /*----------------------------*/
6841 /* unary '+' operator */
6842 /*----------------------------*/
6846 fprintf(outfile,"UPLUS (%p) type (",tree);
6847 printTypeChain(tree->ftype,outfile);
6848 fprintf(outfile,")\n");
6849 ast_print(tree->left,outfile,indent+2);
6851 /*------------------------------------------------------------------*/
6852 /*----------------------------*/
6854 /*----------------------------*/
6855 fprintf(outfile,"ADD (%p) type (",tree);
6856 printTypeChain(tree->ftype,outfile);
6857 fprintf(outfile,")\n");
6858 ast_print(tree->left,outfile,indent+2);
6859 ast_print(tree->right,outfile,indent+2);
6862 /*------------------------------------------------------------------*/
6863 /*----------------------------*/
6865 /*----------------------------*/
6866 case '-': /* can be unary */
6868 fprintf(outfile,"UMINUS (%p) type (",tree);
6869 printTypeChain(tree->ftype,outfile);
6870 fprintf(outfile,")\n");
6871 ast_print(tree->left,outfile,indent+2);
6873 /*------------------------------------------------------------------*/
6874 /*----------------------------*/
6876 /*----------------------------*/
6877 fprintf(outfile,"SUB (%p) type (",tree);
6878 printTypeChain(tree->ftype,outfile);
6879 fprintf(outfile,")\n");
6880 ast_print(tree->left,outfile,indent+2);
6881 ast_print(tree->right,outfile,indent+2);
6884 /*------------------------------------------------------------------*/
6885 /*----------------------------*/
6887 /*----------------------------*/
6889 fprintf(outfile,"COMPL (%p) type (",tree);
6890 printTypeChain(tree->ftype,outfile);
6891 fprintf(outfile,")\n");
6892 ast_print(tree->left,outfile,indent+2);
6894 /*------------------------------------------------------------------*/
6895 /*----------------------------*/
6897 /*----------------------------*/
6899 fprintf(outfile,"NOT (%p) type (",tree);
6900 printTypeChain(tree->ftype,outfile);
6901 fprintf(outfile,")\n");
6902 ast_print(tree->left,outfile,indent+2);
6904 /*------------------------------------------------------------------*/
6905 /*----------------------------*/
6907 /*----------------------------*/
6909 fprintf(outfile,"RRC (%p) type (",tree);
6910 printTypeChain(tree->ftype,outfile);
6911 fprintf(outfile,")\n");
6912 ast_print(tree->left,outfile,indent+2);
6916 fprintf(outfile,"RLC (%p) type (",tree);
6917 printTypeChain(tree->ftype,outfile);
6918 fprintf(outfile,")\n");
6919 ast_print(tree->left,outfile,indent+2);
6922 fprintf(outfile,"SWAP (%p) type (",tree);
6923 printTypeChain(tree->ftype,outfile);
6924 fprintf(outfile,")\n");
6925 ast_print(tree->left,outfile,indent+2);
6928 fprintf(outfile,"GETHBIT (%p) type (",tree);
6929 printTypeChain(tree->ftype,outfile);
6930 fprintf(outfile,")\n");
6931 ast_print(tree->left,outfile,indent+2);
6934 fprintf(outfile,"GETABIT (%p) type (",tree);
6935 printTypeChain(tree->ftype,outfile);
6936 fprintf(outfile,")\n");
6937 ast_print(tree->left,outfile,indent+2);
6938 ast_print(tree->right,outfile,indent+2);
6941 fprintf(outfile,"GETBYTE (%p) type (",tree);
6942 printTypeChain(tree->ftype,outfile);
6943 fprintf(outfile,")\n");
6944 ast_print(tree->left,outfile,indent+2);
6945 ast_print(tree->right,outfile,indent+2);
6948 fprintf(outfile,"GETWORD (%p) type (",tree);
6949 printTypeChain(tree->ftype,outfile);
6950 fprintf(outfile,")\n");
6951 ast_print(tree->left,outfile,indent+2);
6952 ast_print(tree->right,outfile,indent+2);
6955 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6956 printTypeChain(tree->ftype,outfile);
6957 fprintf(outfile,")\n");
6958 ast_print(tree->left,outfile,indent+2);
6959 ast_print(tree->right,outfile,indent+2);
6962 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6963 printTypeChain(tree->ftype,outfile);
6964 fprintf(outfile,")\n");
6965 ast_print(tree->left,outfile,indent+2);
6966 ast_print(tree->right,outfile,indent+2);
6968 /*------------------------------------------------------------------*/
6969 /*----------------------------*/
6971 /*----------------------------*/
6972 case CAST: /* change the type */
6973 fprintf(outfile,"CAST (%p) from type (",tree);
6974 printTypeChain(tree->right->ftype,outfile);
6975 fprintf(outfile,") to type (");
6976 printTypeChain(tree->ftype,outfile);
6977 fprintf(outfile,")\n");
6978 ast_print(tree->right,outfile,indent+2);
6982 fprintf(outfile,"ANDAND (%p) type (",tree);
6983 printTypeChain(tree->ftype,outfile);
6984 fprintf(outfile,")\n");
6985 ast_print(tree->left,outfile,indent+2);
6986 ast_print(tree->right,outfile,indent+2);
6989 fprintf(outfile,"OROR (%p) type (",tree);
6990 printTypeChain(tree->ftype,outfile);
6991 fprintf(outfile,")\n");
6992 ast_print(tree->left,outfile,indent+2);
6993 ast_print(tree->right,outfile,indent+2);
6996 /*------------------------------------------------------------------*/
6997 /*----------------------------*/
6998 /* comparison operators */
6999 /*----------------------------*/
7001 fprintf(outfile,"GT(>) (%p) type (",tree);
7002 printTypeChain(tree->ftype,outfile);
7003 fprintf(outfile,")\n");
7004 ast_print(tree->left,outfile,indent+2);
7005 ast_print(tree->right,outfile,indent+2);
7008 fprintf(outfile,"LT(<) (%p) type (",tree);
7009 printTypeChain(tree->ftype,outfile);
7010 fprintf(outfile,")\n");
7011 ast_print(tree->left,outfile,indent+2);
7012 ast_print(tree->right,outfile,indent+2);
7015 fprintf(outfile,"LE(<=) (%p) type (",tree);
7016 printTypeChain(tree->ftype,outfile);
7017 fprintf(outfile,")\n");
7018 ast_print(tree->left,outfile,indent+2);
7019 ast_print(tree->right,outfile,indent+2);
7022 fprintf(outfile,"GE(>=) (%p) type (",tree);
7023 printTypeChain(tree->ftype,outfile);
7024 fprintf(outfile,")\n");
7025 ast_print(tree->left,outfile,indent+2);
7026 ast_print(tree->right,outfile,indent+2);
7029 fprintf(outfile,"EQ(==) (%p) type (",tree);
7030 printTypeChain(tree->ftype,outfile);
7031 fprintf(outfile,")\n");
7032 ast_print(tree->left,outfile,indent+2);
7033 ast_print(tree->right,outfile,indent+2);
7036 fprintf(outfile,"NE(!=) (%p) type (",tree);
7037 printTypeChain(tree->ftype,outfile);
7038 fprintf(outfile,")\n");
7039 ast_print(tree->left,outfile,indent+2);
7040 ast_print(tree->right,outfile,indent+2);
7041 /*------------------------------------------------------------------*/
7042 /*----------------------------*/
7044 /*----------------------------*/
7045 case SIZEOF: /* evaluate wihout code generation */
7046 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7049 /*------------------------------------------------------------------*/
7050 /*----------------------------*/
7051 /* conditional operator '?' */
7052 /*----------------------------*/
7054 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7055 printTypeChain(tree->ftype,outfile);
7056 fprintf(outfile,")\n");
7057 ast_print(tree->left,outfile,indent+2);
7058 ast_print(tree->right,outfile,indent+2);
7062 fprintf(outfile,"COLON(:) (%p) type (",tree);
7063 printTypeChain(tree->ftype,outfile);
7064 fprintf(outfile,")\n");
7065 ast_print(tree->left,outfile,indent+2);
7066 ast_print(tree->right,outfile,indent+2);
7069 /*------------------------------------------------------------------*/
7070 /*----------------------------*/
7071 /* assignment operators */
7072 /*----------------------------*/
7074 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7075 printTypeChain(tree->ftype,outfile);
7076 fprintf(outfile,")\n");
7077 ast_print(tree->left,outfile,indent+2);
7078 ast_print(tree->right,outfile,indent+2);
7081 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7082 printTypeChain(tree->ftype,outfile);
7083 fprintf(outfile,")\n");
7084 ast_print(tree->left,outfile,indent+2);
7085 ast_print(tree->right,outfile,indent+2);
7088 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7089 printTypeChain(tree->ftype,outfile);
7090 fprintf(outfile,")\n");
7091 ast_print(tree->left,outfile,indent+2);
7092 ast_print(tree->right,outfile,indent+2);
7095 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7096 printTypeChain(tree->ftype,outfile);
7097 fprintf(outfile,")\n");
7098 ast_print(tree->left,outfile,indent+2);
7099 ast_print(tree->right,outfile,indent+2);
7102 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7103 printTypeChain(tree->ftype,outfile);
7104 fprintf(outfile,")\n");
7105 ast_print(tree->left,outfile,indent+2);
7106 ast_print(tree->right,outfile,indent+2);
7109 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7110 printTypeChain(tree->ftype,outfile);
7111 fprintf(outfile,")\n");
7112 ast_print(tree->left,outfile,indent+2);
7113 ast_print(tree->right,outfile,indent+2);
7116 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7117 printTypeChain(tree->ftype,outfile);
7118 fprintf(outfile,")\n");
7119 ast_print(tree->left,outfile,indent+2);
7120 ast_print(tree->right,outfile,indent+2);
7122 /*------------------------------------------------------------------*/
7123 /*----------------------------*/
7125 /*----------------------------*/
7127 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7128 printTypeChain(tree->ftype,outfile);
7129 fprintf(outfile,")\n");
7130 ast_print(tree->left,outfile,indent+2);
7131 ast_print(tree->right,outfile,indent+2);
7133 /*------------------------------------------------------------------*/
7134 /*----------------------------*/
7136 /*----------------------------*/
7138 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7139 printTypeChain(tree->ftype,outfile);
7140 fprintf(outfile,")\n");
7141 ast_print(tree->left,outfile,indent+2);
7142 ast_print(tree->right,outfile,indent+2);
7144 /*------------------------------------------------------------------*/
7145 /*----------------------------*/
7146 /* straight assignemnt */
7147 /*----------------------------*/
7149 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7150 printTypeChain(tree->ftype,outfile);
7151 fprintf(outfile,")\n");
7152 ast_print(tree->left,outfile,indent+2);
7153 ast_print(tree->right,outfile,indent+2);
7155 /*------------------------------------------------------------------*/
7156 /*----------------------------*/
7157 /* comma operator */
7158 /*----------------------------*/
7160 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7161 printTypeChain(tree->ftype,outfile);
7162 fprintf(outfile,")\n");
7163 ast_print(tree->left,outfile,indent+2);
7164 ast_print(tree->right,outfile,indent+2);
7166 /*------------------------------------------------------------------*/
7167 /*----------------------------*/
7169 /*----------------------------*/
7172 fprintf(outfile,"CALL (%p) type (",tree);
7173 printTypeChain(tree->ftype,outfile);
7174 fprintf(outfile,")\n");
7175 ast_print(tree->left,outfile,indent+2);
7176 ast_print(tree->right,outfile,indent+2);
7179 fprintf(outfile,"PARMS\n");
7180 ast_print(tree->left,outfile,indent+2);
7181 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7182 ast_print(tree->right,outfile,indent+2);
7185 /*------------------------------------------------------------------*/
7186 /*----------------------------*/
7187 /* return statement */
7188 /*----------------------------*/
7190 fprintf(outfile,"RETURN (%p) type (",tree);
7192 printTypeChain(tree->right->ftype,outfile);
7194 fprintf(outfile,")\n");
7195 ast_print(tree->right,outfile,indent+2);
7197 /*------------------------------------------------------------------*/
7198 /*----------------------------*/
7199 /* label statement */
7200 /*----------------------------*/
7202 fprintf(outfile,"LABEL (%p)\n",tree);
7203 ast_print(tree->left,outfile,indent+2);
7204 ast_print(tree->right,outfile,indent);
7206 /*------------------------------------------------------------------*/
7207 /*----------------------------*/
7208 /* switch statement */
7209 /*----------------------------*/
7213 fprintf(outfile,"SWITCH (%p) ",tree);
7214 ast_print(tree->left,outfile,0);
7215 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7216 INDENT(indent+2,outfile);
7217 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7218 (int) ulFromVal(val),
7219 tree->values.switchVals.swNum,
7220 (int) ulFromVal(val));
7222 ast_print(tree->right,outfile,indent);
7225 /*------------------------------------------------------------------*/
7226 /*----------------------------*/
7228 /*----------------------------*/
7230 fprintf(outfile,"IF (%p) \n",tree);
7231 ast_print(tree->left,outfile,indent+2);
7232 if (tree->trueLabel) {
7233 INDENT(indent+2,outfile);
7234 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7236 if (tree->falseLabel) {
7237 INDENT(indent+2,outfile);
7238 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7240 ast_print(tree->right,outfile,indent+2);
7242 /*----------------------------*/
7243 /* goto Statement */
7244 /*----------------------------*/
7246 fprintf(outfile,"GOTO (%p) \n",tree);
7247 ast_print(tree->left,outfile,indent+2);
7248 fprintf(outfile,"\n");
7250 /*------------------------------------------------------------------*/
7251 /*----------------------------*/
7253 /*----------------------------*/
7255 fprintf(outfile,"FOR (%p) \n",tree);
7256 if (AST_FOR( tree, initExpr)) {
7257 INDENT(indent+2,outfile);
7258 fprintf(outfile,"INIT EXPR ");
7259 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7261 if (AST_FOR( tree, condExpr)) {
7262 INDENT(indent+2,outfile);
7263 fprintf(outfile,"COND EXPR ");
7264 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7266 if (AST_FOR( tree, loopExpr)) {
7267 INDENT(indent+2,outfile);
7268 fprintf(outfile,"LOOP EXPR ");
7269 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7271 fprintf(outfile,"FOR LOOP BODY \n");
7272 ast_print(tree->left,outfile,indent+2);
7275 fprintf(outfile,"CRITICAL (%p) \n",tree);
7276 ast_print(tree->left,outfile,indent+2);
7284 ast_print(t,stdout,0);
7287 /*-----------------------------------------------------------------*/
7288 /* astErrors : returns non-zero if errors present in tree */
7289 /*-----------------------------------------------------------------*/
7290 int astErrors(ast *t)
7299 if (t->type == EX_VALUE
7300 && t->opval.val->sym
7301 && t->opval.val->sym->undefined)
7304 errors += astErrors(t->left);
7305 errors += astErrors(t->right);