1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
546 /* if this is a label resolve it from the labelTab */
547 if (IS_AST_VALUE (tree) &&
548 tree->opval.val->sym &&
549 tree->opval.val->sym->islbl)
552 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
553 tree->opval.val->sym->name);
556 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
557 tree->opval.val->sym->name);
559 tree->opval.val->sym = csym;
561 goto resolveChildren;
564 /* do only for leafs */
565 if (IS_AST_VALUE (tree) &&
566 tree->opval.val->sym &&
567 !tree->opval.val->sym->implicit)
570 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
572 /* if found in the symbol table & they are not the same */
573 if (csym && tree->opval.val->sym != csym)
575 tree->opval.val->sym = csym;
576 tree->opval.val->type = csym->type;
577 tree->opval.val->etype = csym->etype;
580 /* if not found in the symbol table */
581 /* mark it as undefined & assume it */
582 /* is an integer in data space */
583 if (!csym && !tree->opval.val->sym->implicit)
586 /* if this is a function name then */
587 /* mark it as returning an int */
590 tree->opval.val->sym->type = newLink (DECLARATOR);
591 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
592 tree->opval.val->sym->type->next =
593 tree->opval.val->sym->etype = newIntLink ();
594 tree->opval.val->etype = tree->opval.val->etype;
595 tree->opval.val->type = tree->opval.val->sym->type;
596 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
597 tree->opval.val->sym->name);
598 //tree->opval.val->sym->undefined = 1;
599 allocVariables (tree->opval.val->sym);
603 tree->opval.val->sym->undefined = 1;
604 tree->opval.val->type =
605 tree->opval.val->etype = newIntLink ();
606 tree->opval.val->sym->type =
607 tree->opval.val->sym->etype = newIntLink ();
613 resolveSymbols (tree->left);
614 resolveSymbols (tree->right);
619 /*------------------------------------------------------------------------*/
620 /* setAstFileLine - walks a ast tree & sets the file name and line number */
621 /*------------------------------------------------------------------------*/
622 int setAstFileLine (ast * tree, char *filename, int lineno)
627 tree->filename = filename;
628 tree->lineno = lineno;
629 setAstFileLine (tree->left, filename, lineno);
630 setAstFileLine (tree->right, filename, lineno);
634 /*-----------------------------------------------------------------*/
635 /* funcOfType :- function of type with name */
636 /*-----------------------------------------------------------------*/
638 funcOfType (char *name, sym_link * type, sym_link * argType,
642 /* create the symbol */
643 sym = newSymbol (name, 0);
645 /* setup return value */
646 sym->type = newLink (DECLARATOR);
647 DCL_TYPE (sym->type) = FUNCTION;
648 sym->type->next = copyLinkChain (type);
649 sym->etype = getSpec (sym->type);
650 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
652 /* if arguments required */
656 args = FUNC_ARGS(sym->type) = newValue ();
660 args->type = copyLinkChain (argType);
661 args->etype = getSpec (args->type);
662 SPEC_EXTR(args->etype)=1;
665 args = args->next = newValue ();
672 allocVariables (sym);
677 /*-----------------------------------------------------------------*/
678 /* funcOfTypeVarg :- function of type with name and argtype */
679 /*-----------------------------------------------------------------*/
681 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
686 /* create the symbol */
687 sym = newSymbol (name, 0);
689 /* setup return value */
690 sym->type = newLink (DECLARATOR);
691 DCL_TYPE (sym->type) = FUNCTION;
692 sym->type->next = typeFromStr(rtype);
693 sym->etype = getSpec (sym->type);
695 /* if arguments required */
698 args = FUNC_ARGS(sym->type) = newValue ();
700 for ( i = 0 ; i < nArgs ; i++ ) {
701 args->type = typeFromStr(atypes[i]);
702 args->etype = getSpec (args->type);
703 SPEC_EXTR(args->etype)=1;
704 if ((i + 1) == nArgs) break;
705 args = args->next = newValue ();
712 allocVariables (sym);
717 /*-----------------------------------------------------------------*/
718 /* reverseParms - will reverse a parameter tree */
719 /*-----------------------------------------------------------------*/
721 reverseParms (ast * ptree)
727 /* top down if we find a nonParm tree then quit */
728 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
730 /* The various functions expect the parameter tree to be right heavy. */
731 /* Rotate the tree to be left heavy so that after reversal it is */
732 /* right heavy again. */
733 while ((ttree = ptree->right) && ttree->type == EX_OP &&
734 ttree->opval.op == PARAM)
736 ptree->right = ttree->right;
737 ttree->right = ttree->left;
738 ttree->left = ptree->left;
744 ptree->left = ptree->right;
745 ptree->right = ttree;
747 reverseParms (ptree->left);
748 reverseParms (ptree->right);
754 /*-----------------------------------------------------------------*/
755 /* processParms - makes sure the parameters are okay and do some */
756 /* processing with them */
757 /*-----------------------------------------------------------------*/
759 processParms (ast *func,
762 int *parmNumber, /* unused, although updated */
765 RESULT_TYPE resultType;
768 /* if none of them exist */
769 if (!defParm && !*actParm)
774 if (getenv("DEBUG_SANITY"))
776 fprintf (stderr, "processParms: %s ", defParm->name);
778 /* make sure the type is complete and sane */
779 checkTypeSanity(defParm->etype, defParm->name);
782 if (IS_CODEPTR (func->ftype))
783 functype = func->ftype->next;
785 functype = func->ftype;
787 /* if the function is being called via a pointer & */
788 /* it has not been defined reentrant then we cannot */
789 /* have parameters */
790 /* PIC16 port can... */
791 if (!TARGET_IS_PIC16)
793 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
795 werror (E_NONRENT_ARGS);
801 /* if defined parameters ended but actual parameters */
802 /* exist and this is not defined as a variable arg */
803 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
805 werror (E_TOO_MANY_PARMS);
809 /* if defined parameters present but no actual parameters */
810 if (defParm && !*actParm)
812 werror (E_TOO_FEW_PARMS);
816 /* if this is a PARAM node then match left & right */
817 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
819 (*actParm)->decorated = 1;
820 return (processParms (func, defParm,
821 &(*actParm)->left, parmNumber, FALSE) ||
822 processParms (func, defParm ? defParm->next : NULL,
823 &(*actParm)->right, parmNumber, rightmost));
825 else if (defParm) /* not vararg */
827 /* If we have found a value node by following only right-hand links,
828 * then we know that there are no more values after us.
830 * Therefore, if there are more defined parameters, the caller didn't
833 if (rightmost && defParm->next)
835 werror (E_TOO_FEW_PARMS);
840 /* decorate parameter */
841 resultType = defParm ? getResultTypeFromType (defParm->type) :
843 *actParm = decorateType (*actParm, resultType);
845 if (IS_VOID((*actParm)->ftype))
847 werror (E_VOID_VALUE_USED);
851 /* If this is a varargs function... */
852 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
857 /* don't perform integer promotion of explicitly typecasted variable arguments
858 * if sdcc extensions are enabled */
859 if (options.std_sdcc &&
860 (IS_CAST_OP (*actParm) ||
861 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
862 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
864 /* Parameter was explicitly typecast; don't touch it. */
868 ftype = (*actParm)->ftype;
870 /* If it's a char, upcast to int. */
871 if (IS_INTEGRAL (ftype)
872 && (getSize (ftype) < (unsigned) INTSIZE))
874 newType = newAst_LINK(INTTYPE);
877 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
879 newType = newAst_LINK (copyLinkChain(ftype));
880 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
883 if (IS_AGGREGATE (ftype))
885 newType = newAst_LINK (copyLinkChain (ftype));
886 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
891 /* cast required; change this op to a cast. */
892 (*actParm)->decorated = 0;
893 *actParm = newNode (CAST, newType, *actParm);
894 (*actParm)->filename = (*actParm)->right->filename;
895 (*actParm)->lineno = (*actParm)->right->lineno;
897 decorateType (*actParm, RESULT_TYPE_NONE);
902 /* if defined parameters ended but actual has not & */
904 if (!defParm && *actParm &&
905 (options.stackAuto || IFFUNC_ISREENT (functype)))
908 resolveSymbols (*actParm);
910 /* the parameter type must be at least castable */
911 if (compareType (defParm->type, (*actParm)->ftype) == 0)
913 werror (E_INCOMPAT_TYPES);
914 printFromToType ((*actParm)->ftype, defParm->type);
918 /* if the parameter is castable then add the cast */
919 if (compareType (defParm->type, (*actParm)->ftype) < 0)
923 resultType = getResultTypeFromType (defParm->etype);
924 pTree = resolveSymbols (copyAst (*actParm));
926 /* now change the current one to a cast */
927 (*actParm)->type = EX_OP;
928 (*actParm)->opval.op = CAST;
929 (*actParm)->left = newAst_LINK (defParm->type);
930 (*actParm)->right = pTree;
931 (*actParm)->decorated = 0; /* force typechecking */
932 decorateType (*actParm, resultType);
935 /* make a copy and change the regparm type to the defined parm */
936 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
937 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
938 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
940 /* if the function is being called via a pointer & */
941 /* this parameter is not passed in registers */
942 /* then the function must be defined reentrant */
943 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
944 !IFFUNC_ISREENT (functype) && !options.stackAuto)
946 werror (E_NONRENT_ARGS);
955 /*-----------------------------------------------------------------*/
956 /* createIvalType - generates ival for basic types */
957 /*-----------------------------------------------------------------*/
959 createIvalType (ast * sym, sym_link * type, initList * ilist)
963 /* if initList is deep */
964 if (ilist->type == INIT_DEEP)
965 ilist = ilist->init.deep;
967 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
968 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
971 /*-----------------------------------------------------------------*/
972 /* createIvalStruct - generates initial value for structures */
973 /*-----------------------------------------------------------------*/
975 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
982 sflds = SPEC_STRUCT (type)->fields;
983 if (ilist->type != INIT_DEEP)
985 werror (E_INIT_STRUCT, "");
989 iloop = ilist->init.deep;
991 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
993 /* if we have come to end */
997 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
998 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
999 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
1000 iloop, rast, rootValue)),
1007 if (IS_AST_VALUE (sym))
1008 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1009 W_EXCESS_INITIALIZERS, "struct",
1010 sym->opval.val->sym->name);
1012 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1019 /*-----------------------------------------------------------------*/
1020 /* createIvalArray - generates code for array initialization */
1021 /*-----------------------------------------------------------------*/
1023 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1027 int lcnt = 0, size = 0;
1028 literalList *literalL;
1030 /* take care of the special case */
1031 /* array of characters can be init */
1033 if (IS_CHAR (type->next))
1034 if ((rast = createIvalCharPtr (sym,
1036 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1039 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1041 /* not the special case */
1042 if (ilist->type != INIT_DEEP)
1044 werror (E_INIT_STRUCT, "");
1048 iloop = ilist->init.deep;
1049 lcnt = DCL_ELEM (type);
1051 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1055 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1057 rast = newNode(ARRAYINIT, aSym, NULL);
1058 rast->values.constlist = literalL;
1060 // Make sure size is set to length of initializer list.
1064 iloop = iloop->next;
1067 if (lcnt && size > lcnt)
1069 // Array size was specified, and we have more initializers than needed.
1070 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1071 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1080 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1081 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1082 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1083 iloop = (iloop ? iloop->next : NULL);
1089 /* no of elements given and we */
1090 /* have generated for all of them */
1093 // is this a better way? at least it won't crash
1094 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1095 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1102 /* if we have not been given a size */
1103 if (!DCL_ELEM (type))
1105 /* check, if it's a flexible array */
1106 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1107 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1109 DCL_ELEM (type) = size;
1112 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1116 /*-----------------------------------------------------------------*/
1117 /* createIvalCharPtr - generates initial values for char pointers */
1118 /*-----------------------------------------------------------------*/
1120 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1125 /* if this is a pointer & right is a literal array then */
1126 /* just assignment will do */
1127 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1128 SPEC_SCLS (iexpr->etype) == S_CODE)
1129 && IS_ARRAY (iexpr->ftype)))
1130 return newNode ('=', sym, iexpr);
1132 /* left side is an array so we have to assign each element */
1133 if ((IS_LITERAL (iexpr->etype) ||
1134 SPEC_SCLS (iexpr->etype) == S_CODE)
1135 && IS_ARRAY (iexpr->ftype))
1137 /* for each character generate an assignment */
1138 /* to the array element */
1139 char *s = SPEC_CVAL (iexpr->etype).v_char;
1141 unsigned int symsize = getSize (type);
1143 size = getSize (iexpr->ftype);
1144 if (symsize && size>symsize)
1146 if (size>(symsize+1))
1148 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1150 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1156 for (i=0;i<size;i++)
1158 rast = newNode (NULLOP,
1162 newAst_VALUE (valueFromLit ((float) i))),
1163 newAst_VALUE (valueFromLit (*s))));
1167 // now WE don't need iexpr's symbol anymore
1168 freeStringSymbol(AST_SYMBOL(iexpr));
1170 /* if we have not been given a size */
1171 if (!DCL_ELEM (type))
1173 /* check, if it's a flexible array */
1174 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1175 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1177 DCL_ELEM (type) = size;
1180 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1186 /*-----------------------------------------------------------------*/
1187 /* createIvalPtr - generates initial value for pointers */
1188 /*-----------------------------------------------------------------*/
1190 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1196 if (ilist->type == INIT_DEEP)
1197 ilist = ilist->init.deep;
1199 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1201 /* if character pointer */
1202 if (IS_CHAR (type->next))
1203 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1206 return newNode ('=', sym, iexpr);
1209 /*-----------------------------------------------------------------*/
1210 /* createIval - generates code for initial value */
1211 /*-----------------------------------------------------------------*/
1213 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1220 /* if structure then */
1221 if (IS_STRUCT (type))
1222 rast = createIvalStruct (sym, type, ilist, rootValue);
1224 /* if this is a pointer */
1226 rast = createIvalPtr (sym, type, ilist, rootValue);
1228 /* if this is an array */
1229 if (IS_ARRAY (type))
1230 rast = createIvalArray (sym, type, ilist, rootValue);
1232 /* if type is SPECIFIER */
1234 rast = createIvalType (sym, type, ilist);
1237 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1239 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1242 /*-----------------------------------------------------------------*/
1243 /* initAggregates - initialises aggregate variables with initv */
1244 /*-----------------------------------------------------------------*/
1245 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1246 ast *newAst = newAst_VALUE (symbolVal (sym));
1247 return createIval (newAst, sym->type, ival, wid, newAst);
1250 /*-----------------------------------------------------------------*/
1251 /* gatherAutoInit - creates assignment expressions for initial */
1253 /*-----------------------------------------------------------------*/
1255 gatherAutoInit (symbol * autoChain)
1262 for (sym = autoChain; sym; sym = sym->next)
1265 /* resolve the symbols in the ival */
1267 resolveIvalSym (sym->ival, sym->type);
1270 /* if we are PIC16 port,
1271 * and this is a static,
1272 * and have initial value,
1273 * and not S_CODE, don't emit in gs segment,
1274 * but allow glue.c:pic16emitRegularMap to put symbol
1275 * in idata section */
1276 if(TARGET_IS_PIC16 &&
1277 IS_STATIC (sym->etype) && sym->ival
1278 && SPEC_SCLS(sym->etype) != S_CODE) {
1279 SPEC_SCLS (sym->etype) = S_DATA;
1284 /* if this is a static variable & has an */
1285 /* initial value the code needs to be lifted */
1286 /* here to the main portion since they can be */
1287 /* initialised only once at the start */
1288 if (IS_STATIC (sym->etype) && sym->ival &&
1289 SPEC_SCLS (sym->etype) != S_CODE)
1293 /* insert the symbol into the symbol table */
1294 /* with level = 0 & name = rname */
1295 newSym = copySymbol (sym);
1296 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1298 /* now lift the code to main */
1299 if (IS_AGGREGATE (sym->type)) {
1300 work = initAggregates (sym, sym->ival, NULL);
1302 if (getNelements(sym->type, sym->ival)>1) {
1303 werrorfl (sym->fileDef, sym->lineDef,
1304 W_EXCESS_INITIALIZERS, "scalar",
1307 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1308 list2expr (sym->ival));
1311 setAstFileLine (work, sym->fileDef, sym->lineDef);
1315 staticAutos = newNode (NULLOP, staticAutos, work);
1322 /* if there is an initial value */
1323 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1325 initList *ilist=sym->ival;
1327 while (ilist->type == INIT_DEEP) {
1328 ilist = ilist->init.deep;
1331 /* update lineno for error msg */
1332 filename = sym->fileDef;
1333 lineno = sym->lineDef;
1334 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1336 if (IS_AGGREGATE (sym->type)) {
1337 work = initAggregates (sym, sym->ival, NULL);
1339 if (getNelements(sym->type, sym->ival)>1) {
1340 werrorfl (sym->fileDef, sym->lineDef,
1341 W_EXCESS_INITIALIZERS, "scalar",
1344 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1345 list2expr (sym->ival));
1349 setAstFileLine (work, sym->fileDef, sym->lineDef);
1353 init = newNode (NULLOP, init, work);
1362 /*-----------------------------------------------------------------*/
1363 /* freeStringSymbol - delete a literal string if no more usage */
1364 /*-----------------------------------------------------------------*/
1365 void freeStringSymbol(symbol *sym) {
1366 /* make sure this is a literal string */
1367 assert (sym->isstrlit);
1368 if (--sym->isstrlit == 0) { // lower the usage count
1369 memmap *segment=SPEC_OCLS(sym->etype);
1371 deleteSetItem(&segment->syms, sym);
1376 /*-----------------------------------------------------------------*/
1377 /* stringToSymbol - creates a symbol from a literal string */
1378 /*-----------------------------------------------------------------*/
1380 stringToSymbol (value * val)
1382 char name[SDCC_NAME_MAX + 1];
1383 static int charLbl = 0;
1388 // have we heard this before?
1389 for (sp = statsg->syms; sp; sp = sp->next)
1392 size = getSize (sym->type);
1393 if (sym->isstrlit && size == getSize (val->type) &&
1394 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1396 // yes, this is old news. Don't publish it again.
1397 sym->isstrlit++; // but raise the usage count
1398 return symbolVal (sym);
1402 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1403 sym = newSymbol (name, 0); /* make it @ level 0 */
1404 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1406 /* copy the type from the value passed */
1407 sym->type = copyLinkChain (val->type);
1408 sym->etype = getSpec (sym->type);
1409 /* change to storage class & output class */
1410 SPEC_SCLS (sym->etype) = S_CODE;
1411 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1412 SPEC_STAT (sym->etype) = 1;
1413 /* make the level & block = 0 */
1414 sym->block = sym->level = 0;
1416 /* create an ival */
1417 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1422 allocVariables (sym);
1425 return symbolVal (sym);
1429 /*-----------------------------------------------------------------*/
1430 /* processBlockVars - will go thru the ast looking for block if */
1431 /* a block is found then will allocate the syms */
1432 /* will also gather the auto inits present */
1433 /*-----------------------------------------------------------------*/
1435 processBlockVars (ast * tree, int *stack, int action)
1440 /* if this is a block */
1441 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1445 if (action == ALLOCATE)
1447 *stack += allocVariables (tree->values.sym);
1448 autoInit = gatherAutoInit (tree->values.sym);
1450 /* if there are auto inits then do them */
1452 tree->left = newNode (NULLOP, autoInit, tree->left);
1454 else /* action is deallocate */
1455 deallocLocal (tree->values.sym);
1458 processBlockVars (tree->left, stack, action);
1459 processBlockVars (tree->right, stack, action);
1464 /*-------------------------------------------------------------*/
1465 /* constExprTree - returns TRUE if this tree is a constant */
1467 /*-------------------------------------------------------------*/
1468 bool constExprTree (ast *cexpr) {
1474 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1476 switch (cexpr->type)
1479 if (IS_AST_LIT_VALUE(cexpr)) {
1480 // this is a literal
1483 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1484 // a function's address will never change
1487 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1488 // an array's address will never change
1491 if (IS_AST_SYM_VALUE(cexpr) &&
1492 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1493 // a symbol in code space will never change
1494 // This is only for the 'char *s="hallo"' case and will have to leave
1495 //printf(" code space symbol");
1500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501 "unexpected link in expression tree\n");
1504 if (cexpr->opval.op==ARRAYINIT) {
1505 // this is a list of literals
1508 if (cexpr->opval.op=='=') {
1509 return constExprTree(cexpr->right);
1511 if (cexpr->opval.op==CAST) {
1512 // cast ignored, maybe we should throw a warning here?
1513 return constExprTree(cexpr->right);
1515 if (cexpr->opval.op=='&') {
1518 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1521 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1526 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1531 /*-----------------------------------------------------------------*/
1532 /* constExprValue - returns the value of a constant expression */
1533 /* or NULL if it is not a constant expression */
1534 /*-----------------------------------------------------------------*/
1536 constExprValue (ast * cexpr, int check)
1538 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1540 /* if this is not a constant then */
1541 if (!IS_LITERAL (cexpr->ftype))
1543 /* then check if this is a literal array
1545 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1546 SPEC_CVAL (cexpr->etype).v_char &&
1547 IS_ARRAY (cexpr->ftype))
1549 value *val = valFromType (cexpr->ftype);
1550 SPEC_SCLS (val->etype) = S_LITERAL;
1551 val->sym = cexpr->opval.val->sym;
1552 val->sym->type = copyLinkChain (cexpr->ftype);
1553 val->sym->etype = getSpec (val->sym->type);
1554 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1558 /* if we are casting a literal value then */
1559 if (IS_AST_OP (cexpr) &&
1560 cexpr->opval.op == CAST &&
1561 IS_LITERAL (cexpr->right->ftype))
1563 return valCastLiteral (cexpr->ftype,
1564 floatFromVal (cexpr->right->opval.val));
1567 if (IS_AST_VALUE (cexpr))
1569 return cexpr->opval.val;
1573 werror (E_CONST_EXPECTED, "found expression");
1578 /* return the value */
1579 if (IS_AST_VALUE (cexpr))
1581 return cexpr->opval.val;
1586 /*-----------------------------------------------------------------*/
1587 /* isLabelInAst - will return true if a given label is found */
1588 /*-----------------------------------------------------------------*/
1590 isLabelInAst (symbol * label, ast * tree)
1592 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1595 if (IS_AST_OP (tree) &&
1596 tree->opval.op == LABEL &&
1597 isSymbolEqual (AST_SYMBOL (tree->left), label))
1600 return isLabelInAst (label, tree->right) &&
1601 isLabelInAst (label, tree->left);
1604 /*-----------------------------------------------------------------*/
1605 /* isLoopCountable - return true if the loop count can be determi- */
1606 /* -ned at compile time . */
1607 /*-----------------------------------------------------------------*/
1609 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1610 symbol ** sym, ast ** init, ast ** end)
1613 /* the loop is considered countable if the following
1614 conditions are true :-
1616 a) initExpr :- <sym> = <const>
1617 b) condExpr :- <sym> < <const1>
1618 c) loopExpr :- <sym> ++
1621 /* first check the initExpr */
1622 if (IS_AST_OP (initExpr) &&
1623 initExpr->opval.op == '=' && /* is assignment */
1624 IS_AST_SYM_VALUE (initExpr->left))
1625 { /* left is a symbol */
1627 *sym = AST_SYMBOL (initExpr->left);
1628 *init = initExpr->right;
1633 /* don't reverse loop with volatile counter */
1634 if (IS_VOLATILE ((*sym)->type))
1637 /* for now the symbol has to be of
1639 if (!IS_INTEGRAL ((*sym)->type))
1642 /* now check condExpr */
1643 if (IS_AST_OP (condExpr))
1646 switch (condExpr->opval.op)
1649 if (IS_AST_SYM_VALUE (condExpr->left) &&
1650 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1651 IS_AST_LIT_VALUE (condExpr->right))
1653 *end = condExpr->right;
1659 if (IS_AST_OP (condExpr->left) &&
1660 condExpr->left->opval.op == '>' &&
1661 IS_AST_LIT_VALUE (condExpr->left->right) &&
1662 IS_AST_SYM_VALUE (condExpr->left->left) &&
1663 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1666 *end = newNode ('+', condExpr->left->right,
1667 newAst_VALUE (constCharVal (1)));
1680 /* check loop expression is of the form <sym>++ */
1681 if (!IS_AST_OP (loopExpr))
1684 /* check if <sym> ++ */
1685 if (loopExpr->opval.op == INC_OP)
1691 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1692 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1699 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1700 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1708 if (loopExpr->opval.op == ADD_ASSIGN)
1711 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1712 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1713 IS_AST_LIT_VALUE (loopExpr->right) &&
1714 AST_ULONG_VALUE (loopExpr->right) != 1)
1722 /*-----------------------------------------------------------------*/
1723 /* astHasVolatile - returns true if ast contains any volatile */
1724 /*-----------------------------------------------------------------*/
1726 astHasVolatile (ast * tree)
1731 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1734 if (IS_AST_OP (tree))
1735 return astHasVolatile (tree->left) ||
1736 astHasVolatile (tree->right);
1741 /*-----------------------------------------------------------------*/
1742 /* astHasPointer - return true if the ast contains any ptr variable */
1743 /*-----------------------------------------------------------------*/
1745 astHasPointer (ast * tree)
1750 if (IS_AST_LINK (tree))
1753 /* if we hit an array expression then check
1754 only the left side */
1755 if (IS_AST_OP (tree) && tree->opval.op == '[')
1756 return astHasPointer (tree->left);
1758 if (IS_AST_VALUE (tree))
1759 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1761 return astHasPointer (tree->left) ||
1762 astHasPointer (tree->right);
1766 /*-----------------------------------------------------------------*/
1767 /* astHasSymbol - return true if the ast has the given symbol */
1768 /*-----------------------------------------------------------------*/
1770 astHasSymbol (ast * tree, symbol * sym)
1772 if (!tree || IS_AST_LINK (tree))
1775 if (IS_AST_VALUE (tree))
1777 if (IS_AST_SYM_VALUE (tree))
1778 return isSymbolEqual (AST_SYMBOL (tree), sym);
1783 return astHasSymbol (tree->left, sym) ||
1784 astHasSymbol (tree->right, sym);
1787 /*-----------------------------------------------------------------*/
1788 /* astHasDeref - return true if the ast has an indirect access */
1789 /*-----------------------------------------------------------------*/
1791 astHasDeref (ast * tree)
1793 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1796 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1798 return astHasDeref (tree->left) || astHasDeref (tree->right);
1801 /*-----------------------------------------------------------------*/
1802 /* isConformingBody - the loop body has to conform to a set of */
1803 /* rules for the loop to be considered reversible read on for rules*/
1804 /*-----------------------------------------------------------------*/
1806 isConformingBody (ast * pbody, symbol * sym, ast * body)
1809 /* we are going to do a pre-order traversal of the
1810 tree && check for the following conditions. (essentially
1811 a set of very shallow tests )
1812 a) the sym passed does not participate in any arithmetic operation
1813 b) There are no function calls
1814 c) all jumps are within the body
1815 d) address of loop control variable not taken
1816 e) if an assignment has a pointer on the left hand side make sure
1817 right does not have loop control variable
1820 /* if we reach the end or a leaf then true */
1821 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1824 /* if anything else is "volatile" */
1825 if (IS_VOLATILE (TETYPE (pbody)))
1828 /* we will walk the body in a pre-order traversal for
1830 switch (pbody->opval.op)
1832 /*------------------------------------------------------------------*/
1834 // if the loopvar is used as an index
1835 /* array op is commutative -- must check both left & right */
1836 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1839 return isConformingBody (pbody->right, sym, body)
1840 && isConformingBody (pbody->left, sym, body);
1842 /*------------------------------------------------------------------*/
1847 /*------------------------------------------------------------------*/
1851 /* sure we are not sym is not modified */
1853 IS_AST_SYM_VALUE (pbody->left) &&
1854 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1858 IS_AST_SYM_VALUE (pbody->right) &&
1859 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1864 /*------------------------------------------------------------------*/
1866 case '*': /* can be unary : if right is null then unary operation */
1871 /* if right is NULL then unary operation */
1872 /*------------------------------------------------------------------*/
1873 /*----------------------------*/
1875 /*----------------------------*/
1878 if (IS_AST_SYM_VALUE (pbody->left) &&
1879 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1882 return isConformingBody (pbody->left, sym, body);
1886 if (astHasSymbol (pbody->left, sym) ||
1887 astHasSymbol (pbody->right, sym))
1892 /*------------------------------------------------------------------*/
1903 if (IS_AST_SYM_VALUE (pbody->left) &&
1904 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1907 if (IS_AST_SYM_VALUE (pbody->right) &&
1908 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1911 return isConformingBody (pbody->left, sym, body) &&
1912 isConformingBody (pbody->right, sym, body);
1920 if (IS_AST_SYM_VALUE (pbody->left) &&
1921 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1923 return isConformingBody (pbody->left, sym, body);
1925 /*------------------------------------------------------------------*/
1937 case SIZEOF: /* evaluate wihout code generation */
1939 if (IS_AST_SYM_VALUE (pbody->left) &&
1940 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1943 if (IS_AST_SYM_VALUE (pbody->right) &&
1944 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1947 return isConformingBody (pbody->left, sym, body) &&
1948 isConformingBody (pbody->right, sym, body);
1950 /*------------------------------------------------------------------*/
1953 /* if left has a pointer & right has loop
1954 control variable then we cannot */
1955 if (astHasPointer (pbody->left) &&
1956 astHasSymbol (pbody->right, sym))
1958 if (astHasVolatile (pbody->left))
1961 if (IS_AST_SYM_VALUE (pbody->left)) {
1962 // if the loopvar has an assignment
1963 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1965 // if the loopvar is used in another (maybe conditional) block
1966 if (astHasSymbol (pbody->right, sym) &&
1967 (pbody->level >= body->level)) {
1972 if (astHasVolatile (pbody->left))
1975 if (astHasDeref(pbody->right))
1978 return isConformingBody (pbody->left, sym, body) &&
1979 isConformingBody (pbody->right, sym, body);
1990 assert ("Parser should not have generated this\n");
1992 /*------------------------------------------------------------------*/
1993 /*----------------------------*/
1994 /* comma operator */
1995 /*----------------------------*/
1997 return isConformingBody (pbody->left, sym, body) &&
1998 isConformingBody (pbody->right, sym, body);
2000 /*------------------------------------------------------------------*/
2001 /*----------------------------*/
2003 /*----------------------------*/
2005 /* if local & not passed as parameter &
2006 not used to find the function then ok */
2007 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2008 !astHasSymbol (pbody->left, sym))
2014 /*------------------------------------------------------------------*/
2015 /*----------------------------*/
2016 /* return statement */
2017 /*----------------------------*/
2022 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2027 if (astHasSymbol (pbody->left, sym))
2034 return isConformingBody (pbody->left, sym, body) &&
2035 isConformingBody (pbody->right, sym, body);
2038 /*-----------------------------------------------------------------*/
2039 /* isLoopReversible - takes a for loop as input && returns true */
2040 /* if the for loop is reversible. If yes will set the value of */
2041 /* the loop control var & init value & termination value */
2042 /*-----------------------------------------------------------------*/
2044 isLoopReversible (ast * loop, symbol ** loopCntrl,
2045 ast ** init, ast ** end)
2047 /* if option says don't do it then don't */
2048 if (optimize.noLoopReverse)
2050 /* there are several tests to determine this */
2052 /* for loop has to be of the form
2053 for ( <sym> = <const1> ;
2054 [<sym> < <const2>] ;
2055 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2057 if (!isLoopCountable (AST_FOR (loop, initExpr),
2058 AST_FOR (loop, condExpr),
2059 AST_FOR (loop, loopExpr),
2060 loopCntrl, init, end))
2063 /* now do some serious checking on the body of the loop
2066 return isConformingBody (loop->left, *loopCntrl, loop->left);
2070 /*-----------------------------------------------------------------*/
2071 /* replLoopSym - replace the loop sym by loop sym -1 */
2072 /*-----------------------------------------------------------------*/
2074 replLoopSym (ast * body, symbol * sym)
2077 if (!body || IS_AST_LINK (body))
2080 if (IS_AST_SYM_VALUE (body))
2083 if (isSymbolEqual (AST_SYMBOL (body), sym))
2087 body->opval.op = '-';
2088 body->left = newAst_VALUE (symbolVal (sym));
2089 body->right = newAst_VALUE (constCharVal (1));
2097 replLoopSym (body->left, sym);
2098 replLoopSym (body->right, sym);
2102 /*-----------------------------------------------------------------*/
2103 /* reverseLoop - do the actual loop reversal */
2104 /*-----------------------------------------------------------------*/
2106 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2110 /* create the following tree
2115 if (sym) goto for_continue ;
2118 /* put it together piece by piece */
2119 rloop = newNode (NULLOP,
2120 createIf (newAst_VALUE (symbolVal (sym)),
2122 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2125 newAst_VALUE (symbolVal (sym)),
2128 replLoopSym (loop->left, sym);
2129 setAstFileLine (rloop, init->filename, init->lineno);
2131 rloop = newNode (NULLOP,
2133 newAst_VALUE (symbolVal (sym)),
2134 newNode ('-', end, init)),
2135 createLabel (AST_FOR (loop, continueLabel),
2139 newNode (SUB_ASSIGN,
2140 newAst_VALUE (symbolVal (sym)),
2141 newAst_VALUE (constCharVal (1))),
2144 rloop->lineno=init->lineno;
2145 return decorateType (rloop, RESULT_TYPE_NONE);
2149 /*-----------------------------------------------------------------*/
2150 /* searchLitOp - search tree (*ops only) for an ast with literal */
2151 /*-----------------------------------------------------------------*/
2153 searchLitOp (ast *tree, ast **parent, const char *ops)
2157 if (tree && optimize.global_cse)
2159 /* is there a literal operand? */
2161 IS_AST_OP(tree->right) &&
2162 tree->right->right &&
2163 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2165 if (IS_LITERAL (RTYPE (tree->right)) !=
2166 IS_LITERAL (LTYPE (tree->right)))
2168 tree->right->decorated = 0;
2169 tree->decorated = 0;
2173 ret = searchLitOp (tree->right, parent, ops);
2178 IS_AST_OP(tree->left) &&
2179 tree->left->right &&
2180 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2182 if (IS_LITERAL (RTYPE (tree->left)) !=
2183 IS_LITERAL (LTYPE (tree->left)))
2185 tree->left->decorated = 0;
2186 tree->decorated = 0;
2190 ret = searchLitOp (tree->left, parent, ops);
2198 /*-----------------------------------------------------------------*/
2199 /* getResultFromType */
2200 /*-----------------------------------------------------------------*/
2202 getResultTypeFromType (sym_link *type)
2204 /* type = getSpec (type); */
2206 return RESULT_TYPE_BIT;
2207 if (IS_BITFIELD (type))
2209 int blen = SPEC_BLEN (type);
2212 return RESULT_TYPE_BIT;
2214 return RESULT_TYPE_CHAR;
2215 return RESULT_TYPE_INT;
2218 return RESULT_TYPE_CHAR;
2219 if (IS_INT (type) && !IS_LONG (type))
2220 return RESULT_TYPE_INT;
2221 return RESULT_TYPE_OTHER;
2224 /*-----------------------------------------------------------------*/
2225 /* addCast - adds casts to a type specified by RESULT_TYPE */
2226 /*-----------------------------------------------------------------*/
2228 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2231 bool upCasted = FALSE;
2235 case RESULT_TYPE_NONE:
2236 /* if thing smaller than int must be promoted to int */
2238 getSize (tree->etype) >= INTSIZE)
2239 /* promotion not necessary or already an int */
2241 /* char and bits: promote to int */
2242 newLink = newIntLink();
2245 case RESULT_TYPE_BIT:
2247 /* already an int */
2248 bitsForType (tree->etype) >= 16 ||
2249 /* bit to bit operation: don't promote, the code generators
2250 hopefully know everything about promotion rules */
2251 bitsForType (tree->etype) == 1)
2253 newLink = newIntLink();
2256 case RESULT_TYPE_CHAR:
2257 if (IS_CHAR (tree->etype) ||
2258 IS_FLOAT(tree->etype) ||
2259 IS_FIXED(tree->etype))
2261 newLink = newCharLink();
2263 case RESULT_TYPE_INT:
2265 if (getSize (tree->etype) > INTSIZE)
2267 /* warn ("Loosing significant digits"); */
2271 /* char: promote to int */
2273 getSize (tree->etype) >= INTSIZE)
2275 newLink = newIntLink();
2278 case RESULT_TYPE_IFX:
2279 case RESULT_TYPE_OTHER:
2281 /* return type is ifx, long, float: promote char to int */
2282 getSize (tree->etype) >= INTSIZE)
2284 newLink = newIntLink();
2290 tree->decorated = 0;
2291 tree = newNode (CAST, newAst_LINK (newLink), tree);
2292 tree->filename = tree->right->filename;
2293 tree->lineno = tree->right->lineno;
2294 /* keep unsigned type during cast to smaller type,
2295 but not when promoting from char to int */
2297 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2298 return decorateType (tree, resultType);
2301 /*-----------------------------------------------------------------*/
2302 /* resultTypePropagate - decides if resultType can be propagated */
2303 /*-----------------------------------------------------------------*/
2305 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2307 switch (tree->opval.op)
2324 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2325 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2326 return RESULT_TYPE_NONE;
2331 return RESULT_TYPE_NONE;
2335 return RESULT_TYPE_IFX;
2337 return RESULT_TYPE_NONE;
2341 /*-----------------------------------------------------------------*/
2342 /* getLeftResultType - gets type from left branch for propagation */
2343 /*-----------------------------------------------------------------*/
2345 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2347 switch (tree->opval.op)
2351 if (IS_PTR (LTYPE (tree)))
2352 return RESULT_TYPE_NONE;
2354 return getResultTypeFromType (LETYPE (tree));
2356 if (IS_PTR (currFunc->type->next))
2357 return RESULT_TYPE_NONE;
2359 return getResultTypeFromType (currFunc->type->next);
2361 if (!IS_ARRAY (LTYPE (tree)))
2363 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2364 return RESULT_TYPE_CHAR;
2371 /*------------------------------------------------------------------*/
2372 /* gatherImplicitVariables: assigns correct type information to */
2373 /* symbols and values created by replaceAstWithTemporary */
2374 /* and adds the symbols to the declarations list of the */
2375 /* innermost block that contains them */
2376 /*------------------------------------------------------------------*/
2378 gatherImplicitVariables (ast * tree, ast * block)
2383 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2385 /* keep track of containing scope */
2388 if (tree->type == EX_OP && tree->opval.op == '=' &&
2389 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2391 symbol *assignee = tree->left->opval.val->sym;
2393 /* special case for assignment to compiler-generated temporary variable:
2394 compute type of RHS, and set the symbol's type to match */
2395 if (assignee->type == NULL && assignee->infertype) {
2396 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2398 if (dtr != tree->right)
2401 assignee->type = copyLinkChain(TTYPE(dtr));
2402 assignee->etype = getSpec(assignee->type);
2403 SPEC_SCLS (assignee->etype) = S_AUTO;
2404 SPEC_OCLS (assignee->etype) = NULL;
2405 SPEC_EXTR (assignee->etype) = 0;
2406 SPEC_STAT (assignee->etype) = 0;
2407 SPEC_VOLATILE (assignee->etype) = 0;
2408 SPEC_ABSA (assignee->etype) = 0;
2410 wassertl(block != NULL, "implicit variable not contained in block");
2411 wassert(assignee->next == NULL);
2412 if (block != NULL) {
2413 symbol **decl = &(block->values.sym);
2416 wassert(*decl != assignee); /* should not already be in list */
2417 decl = &( (*decl)->next );
2424 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2425 tree->opval.val->type == NULL &&
2426 tree->opval.val->sym &&
2427 tree->opval.val->sym->infertype)
2429 /* fixup type of value for compiler-inferred temporary var */
2430 tree->opval.val->type = tree->opval.val->sym->type;
2431 tree->opval.val->etype = tree->opval.val->sym->etype;
2434 gatherImplicitVariables(tree->left, block);
2435 gatherImplicitVariables(tree->right, block);
2438 /*--------------------------------------------------------------------*/
2439 /* decorateType - compute type for this tree, also does type checking.*/
2440 /* This is done bottom up, since type has to flow upwards. */
2441 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2442 /* result is a char and the operand(s) are int's. */
2443 /* It also does constant folding, and parameter checking. */
2444 /*--------------------------------------------------------------------*/
2446 decorateType (ast * tree, RESULT_TYPE resultType)
2450 RESULT_TYPE resultTypeProp;
2455 /* if already has type then do nothing */
2456 if (tree->decorated)
2459 tree->decorated = 1;
2462 /* print the line */
2463 /* if not block & function */
2464 if (tree->type == EX_OP &&
2465 (tree->opval.op != FUNCTION &&
2466 tree->opval.op != BLOCK &&
2467 tree->opval.op != NULLOP))
2469 filename = tree->filename;
2470 lineno = tree->lineno;
2474 /* if any child is an error | this one is an error do nothing */
2475 if (tree->isError ||
2476 (tree->left && tree->left->isError) ||
2477 (tree->right && tree->right->isError))
2480 /*------------------------------------------------------------------*/
2481 /*----------------------------*/
2482 /* leaf has been reached */
2483 /*----------------------------*/
2484 filename = tree->filename;
2485 lineno = tree->lineno;
2486 /* if this is of type value */
2487 /* just get the type */
2488 if (tree->type == EX_VALUE)
2490 if (IS_LITERAL (tree->opval.val->etype))
2492 /* if this is a character array then declare it */
2493 if (IS_ARRAY (tree->opval.val->type))
2494 tree->opval.val = stringToSymbol (tree->opval.val);
2496 /* otherwise just copy the type information */
2497 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2501 if (tree->opval.val->sym)
2503 /* if the undefined flag is set then give error message */
2504 if (tree->opval.val->sym->undefined)
2506 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2508 TTYPE (tree) = TETYPE (tree) =
2509 tree->opval.val->type = tree->opval.val->sym->type =
2510 tree->opval.val->etype = tree->opval.val->sym->etype =
2511 copyLinkChain (INTTYPE);
2513 else if (tree->opval.val->sym->implicit)
2515 /* if implicit i.e. struct/union member then no type */
2516 TTYPE (tree) = TETYPE (tree) = NULL;
2520 /* copy the type from the value into the ast */
2521 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2523 /* and mark the symbol as referenced */
2524 tree->opval.val->sym->isref = 1;
2528 wassert(0); /* unreached: all values are literals or symbols */
2533 /* if type link for the case of cast */
2534 if (tree->type == EX_LINK)
2536 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2544 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2546 if (tree->left && tree->left->type == EX_OPERAND
2547 && (tree->left->opval.op == INC_OP
2548 || tree->left->opval.op == DEC_OP)
2549 && tree->left->left)
2551 tree->left->right = tree->left->left;
2552 tree->left->left = NULL;
2554 if (tree->right && tree->right->type == EX_OPERAND
2555 && (tree->right->opval.op == INC_OP
2556 || tree->right->opval.op == DEC_OP)
2557 && tree->right->left)
2559 tree->right->right = tree->right->left;
2560 tree->right->left = NULL;
2565 /* Before decorating the left branch we've to decide in dependence
2566 upon tree->opval.op, if resultType can be propagated */
2567 resultTypeProp = resultTypePropagate (tree, resultType);
2569 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2570 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2572 dtl = decorateType (tree->left, resultTypeProp);
2574 /* if an array node, we may need to swap branches */
2575 if (tree->opval.op == '[')
2577 /* determine which is the array & which the index */
2578 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2579 IS_INTEGRAL (LTYPE (tree)))
2581 ast *tempTree = tree->left;
2582 tree->left = tree->right;
2583 tree->right = tempTree;
2587 /* After decorating the left branch there's type information available
2588 in tree->left->?type. If the op is e.g. '=' we extract the type
2589 information from there and propagate it to the right branch. */
2590 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2592 switch (tree->opval.op)
2595 /* delay right side for '?' operator since conditional macro
2596 expansions might rely on this */
2600 /* decorate right side for CALL (parameter list) in processParms();
2601 there is resultType available */
2605 /* don't allocate string if it is a sizeof argument */
2607 dtr = decorateType (tree->right, resultTypeProp);
2611 dtr = decorateType (tree->right, resultTypeProp);
2615 /* this is to take care of situations
2616 when the tree gets rewritten */
2617 if (dtl != tree->left)
2619 if (dtr != tree->right)
2621 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2625 /* depending on type of operator do */
2627 switch (tree->opval.op)
2629 /*------------------------------------------------------------------*/
2630 /*----------------------------*/
2632 /*----------------------------*/
2635 /* first check if this is a array or a pointer */
2636 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2638 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2639 goto errorTreeReturn;
2642 /* check if the type of the idx */
2643 if (!IS_INTEGRAL (RTYPE (tree)))
2645 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2646 goto errorTreeReturn;
2649 /* if the left is an rvalue then error */
2652 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2653 goto errorTreeReturn;
2656 if (IS_LITERAL (RTYPE (tree)))
2658 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2659 int arraySize = DCL_ELEM (LTYPE (tree));
2660 if (arraySize && arrayIndex >= arraySize)
2662 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2667 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2668 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2671 /*------------------------------------------------------------------*/
2672 /*----------------------------*/
2674 /*----------------------------*/
2676 /* if this is not a structure */
2677 if (!IS_STRUCT (LTYPE (tree)))
2679 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2680 goto errorTreeReturn;
2682 TTYPE (tree) = structElemType (LTYPE (tree),
2683 (tree->right->type == EX_VALUE ?
2684 tree->right->opval.val : NULL));
2685 TETYPE (tree) = getSpec (TTYPE (tree));
2688 /*------------------------------------------------------------------*/
2689 /*----------------------------*/
2690 /* struct/union pointer */
2691 /*----------------------------*/
2693 /* if not pointer to a structure */
2694 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2696 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2697 goto errorTreeReturn;
2700 if (!IS_STRUCT (LTYPE (tree)->next))
2702 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2703 goto errorTreeReturn;
2706 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2707 (tree->right->type == EX_VALUE ?
2708 tree->right->opval.val : NULL));
2709 TETYPE (tree) = getSpec (TTYPE (tree));
2711 /* adjust the storage class */
2712 switch (DCL_TYPE(tree->left->ftype)) {
2714 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2717 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2720 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2723 SPEC_SCLS (TETYPE (tree)) = 0;
2726 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2729 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2732 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2735 SPEC_SCLS (TETYPE (tree)) = 0;
2742 /* This breaks with extern declarations, bitfields, and perhaps other */
2743 /* cases (gcse). Let's leave this optimization disabled for now and */
2744 /* ponder if there's a safe way to do this. -- EEP */
2746 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2747 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2749 /* If defined struct type at addr var
2750 then rewrite (&struct var)->member
2752 and define membertype at (addr+offsetof(struct var,member)) temp
2755 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2756 AST_SYMBOL(tree->right));
2758 sym = newSymbol(genSymName (0), 0);
2759 sym->type = TTYPE (tree);
2760 sym->etype = getSpec(sym->type);
2761 sym->lineDef = tree->lineno;
2764 SPEC_STAT (sym->etype) = 1;
2765 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2767 SPEC_ABSA(sym->etype) = 1;
2768 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2771 AST_VALUE (tree) = symbolVal(sym);
2774 tree->type = EX_VALUE;
2782 /*------------------------------------------------------------------*/
2783 /*----------------------------*/
2784 /* ++/-- operation */
2785 /*----------------------------*/
2789 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2790 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2791 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2792 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2801 /*------------------------------------------------------------------*/
2802 /*----------------------------*/
2804 /*----------------------------*/
2805 case '&': /* can be unary */
2806 /* if right is NULL then unary operation */
2807 if (tree->right) /* not an unary operation */
2810 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2812 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2813 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2814 printTypeChain (LTYPE (tree), stderr);
2815 fprintf (stderr, ",");
2816 printTypeChain (RTYPE (tree), stderr);
2817 fprintf (stderr, "\n");
2818 goto errorTreeReturn;
2821 /* if they are both literal */
2822 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2824 tree->type = EX_VALUE;
2825 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2826 valFromType (RETYPE (tree)), '&');
2828 tree->right = tree->left = NULL;
2829 TETYPE (tree) = tree->opval.val->etype;
2830 TTYPE (tree) = tree->opval.val->type;
2834 /* see if this is a GETHBIT operation if yes
2837 ast *otree = optimizeGetHbit (tree, resultType);
2840 return decorateType (otree, RESULT_TYPE_NONE);
2843 /* see if this is a GETABIT operation if yes
2846 ast *otree = optimizeGetAbit (tree, resultType);
2849 return decorateType (otree, RESULT_TYPE_NONE);
2852 /* see if this is a GETBYTE operation if yes
2855 ast *otree = optimizeGetByte (tree, resultType);
2858 return decorateType (otree, RESULT_TYPE_NONE);
2861 /* see if this is a GETWORD operation if yes
2864 ast *otree = optimizeGetWord (tree, resultType);
2867 return decorateType (otree, RESULT_TYPE_NONE);
2870 /* if left is a literal exchange left & right */
2871 if (IS_LITERAL (LTYPE (tree)))
2873 ast *tTree = tree->left;
2874 tree->left = tree->right;
2875 tree->right = tTree;
2878 /* if right is a literal and */
2879 /* we can find a 2nd literal in an and-tree then */
2880 /* rearrange the tree */
2881 if (IS_LITERAL (RTYPE (tree)))
2884 ast *litTree = searchLitOp (tree, &parent, "&");
2888 ast *tTree = litTree->left;
2889 litTree->left = tree->right;
2890 tree->right = tTree;
2891 /* both operands in litTree are literal now */
2892 decorateType (parent, resultType);
2896 LRVAL (tree) = RRVAL (tree) = 1;
2898 TTYPE (tree) = computeType (LTYPE (tree),
2902 TETYPE (tree) = getSpec (TTYPE (tree));
2907 /*------------------------------------------------------------------*/
2908 /*----------------------------*/
2910 /*----------------------------*/
2911 p = newLink (DECLARATOR);
2912 /* if bit field then error */
2913 if (IS_BITVAR (tree->left->etype))
2915 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2916 goto errorTreeReturn;
2919 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2921 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2922 goto errorTreeReturn;
2925 if (IS_FUNC (LTYPE (tree)))
2927 // this ought to be ignored
2928 return (tree->left);
2931 if (IS_LITERAL(LTYPE(tree)))
2933 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2934 goto errorTreeReturn;
2939 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2940 goto errorTreeReturn;
2943 DCL_TYPE (p) = POINTER;
2944 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2945 DCL_TYPE (p) = CPOINTER;
2946 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2947 DCL_TYPE (p) = FPOINTER;
2948 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2949 DCL_TYPE (p) = PPOINTER;
2950 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2951 DCL_TYPE (p) = IPOINTER;
2952 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2953 DCL_TYPE (p) = EEPPOINTER;
2954 else if (SPEC_OCLS(tree->left->etype))
2955 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2957 DCL_TYPE (p) = POINTER;
2959 if (IS_AST_SYM_VALUE (tree->left))
2961 AST_SYMBOL (tree->left)->addrtaken = 1;
2962 AST_SYMBOL (tree->left)->allocreq = 1;
2965 p->next = LTYPE (tree);
2967 TETYPE (tree) = getSpec (TTYPE (tree));
2972 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2973 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2975 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2976 AST_SYMBOL(tree->left->right));
2977 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2978 valueFromLit(element->offset));
2981 tree->type = EX_VALUE;
2982 tree->values.literalFromCast = 1;
2988 /*------------------------------------------------------------------*/
2989 /*----------------------------*/
2991 /*----------------------------*/
2993 /* if the rewrite succeeds then don't go any further */
2995 ast *wtree = optimizeRRCRLC (tree);
2997 return decorateType (wtree, RESULT_TYPE_NONE);
2999 wtree = optimizeSWAP (tree);
3001 return decorateType (wtree, RESULT_TYPE_NONE);
3004 /* if left is a literal exchange left & right */
3005 if (IS_LITERAL (LTYPE (tree)))
3007 ast *tTree = tree->left;
3008 tree->left = tree->right;
3009 tree->right = tTree;
3012 /* if right is a literal and */
3013 /* we can find a 2nd literal in an or-tree then */
3014 /* rearrange the tree */
3015 if (IS_LITERAL (RTYPE (tree)))
3018 ast *litTree = searchLitOp (tree, &parent, "|");
3022 ast *tTree = litTree->left;
3023 litTree->left = tree->right;
3024 tree->right = tTree;
3025 /* both operands in tTree are literal now */
3026 decorateType (parent, resultType);
3031 /*------------------------------------------------------------------*/
3032 /*----------------------------*/
3034 /*----------------------------*/
3036 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3038 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3039 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3040 printTypeChain (LTYPE (tree), stderr);
3041 fprintf (stderr, ",");
3042 printTypeChain (RTYPE (tree), stderr);
3043 fprintf (stderr, "\n");
3044 goto errorTreeReturn;
3047 /* if they are both literal then rewrite the tree */
3048 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3050 tree->type = EX_VALUE;
3051 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3052 valFromType (RETYPE (tree)),
3054 tree->right = tree->left = NULL;
3055 TETYPE (tree) = tree->opval.val->etype;
3056 TTYPE (tree) = tree->opval.val->type;
3060 /* if left is a literal exchange left & right */
3061 if (IS_LITERAL (LTYPE (tree)))
3063 ast *tTree = tree->left;
3064 tree->left = tree->right;
3065 tree->right = tTree;
3068 /* if right is a literal and */
3069 /* we can find a 2nd literal in a xor-tree then */
3070 /* rearrange the tree */
3071 if (IS_LITERAL (RTYPE (tree)) &&
3072 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3075 ast *litTree = searchLitOp (tree, &parent, "^");
3079 ast *tTree = litTree->left;
3080 litTree->left = tree->right;
3081 tree->right = tTree;
3082 /* both operands in litTree are literal now */
3083 decorateType (parent, resultType);
3087 LRVAL (tree) = RRVAL (tree) = 1;
3089 TTYPE (tree) = computeType (LTYPE (tree),
3093 TETYPE (tree) = getSpec (TTYPE (tree));
3097 /*------------------------------------------------------------------*/
3098 /*----------------------------*/
3100 /*----------------------------*/
3102 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3104 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3105 goto errorTreeReturn;
3107 /* if they are both literal then */
3108 /* rewrite the tree */
3109 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3111 tree->type = EX_VALUE;
3112 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3113 valFromType (RETYPE (tree)));
3114 tree->right = tree->left = NULL;
3115 TETYPE (tree) = getSpec (TTYPE (tree) =
3116 tree->opval.val->type);
3120 LRVAL (tree) = RRVAL (tree) = 1;
3122 TETYPE (tree) = getSpec (TTYPE (tree) =
3123 computeType (LTYPE (tree),
3128 /* if right is a literal and */
3129 /* left is also a division by a literal then */
3130 /* rearrange the tree */
3131 if (IS_LITERAL (RTYPE (tree))
3132 /* avoid infinite loop */
3133 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3136 ast *litTree = searchLitOp (tree, &parent, "/");
3139 if (IS_LITERAL (RTYPE (litTree)))
3143 litTree->right = newNode ('*',
3145 copyAst (tree->right));
3146 litTree->right->filename = tree->filename;
3147 litTree->right->lineno = tree->lineno;
3149 tree->right->opval.val = constCharVal (1);
3150 decorateType (parent, resultType);
3154 /* litTree->left is literal: no gcse possible.
3155 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3156 this would cause an infinit loop. */
3157 parent->decorated = 1;
3158 decorateType (litTree, resultType);
3165 /*------------------------------------------------------------------*/
3166 /*----------------------------*/
3168 /*----------------------------*/
3170 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3172 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3173 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3174 printTypeChain (LTYPE (tree), stderr);
3175 fprintf (stderr, ",");
3176 printTypeChain (RTYPE (tree), stderr);
3177 fprintf (stderr, "\n");
3178 goto errorTreeReturn;
3180 /* if they are both literal then */
3181 /* rewrite the tree */
3182 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3184 tree->type = EX_VALUE;
3185 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3186 valFromType (RETYPE (tree)));
3187 tree->right = tree->left = NULL;
3188 TETYPE (tree) = getSpec (TTYPE (tree) =
3189 tree->opval.val->type);
3192 LRVAL (tree) = RRVAL (tree) = 1;
3193 TETYPE (tree) = getSpec (TTYPE (tree) =
3194 computeType (LTYPE (tree),
3200 /*------------------------------------------------------------------*/
3201 /*----------------------------*/
3202 /* address dereference */
3203 /*----------------------------*/
3204 case '*': /* can be unary : if right is null then unary operation */
3207 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3209 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3210 goto errorTreeReturn;
3215 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3216 goto errorTreeReturn;
3218 if (IS_ADDRESS_OF_OP(tree->left))
3220 /* replace *&obj with obj */
3221 return tree->left->left;
3223 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3224 TETYPE (tree) = getSpec (TTYPE (tree));
3225 /* adjust the storage class */
3226 switch (DCL_TYPE(tree->left->ftype)) {
3228 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3231 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3234 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3237 SPEC_SCLS (TETYPE (tree)) = 0;
3240 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3243 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3246 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3249 SPEC_SCLS (TETYPE (tree)) = 0;
3258 /*------------------------------------------------------------------*/
3259 /*----------------------------*/
3260 /* multiplication */
3261 /*----------------------------*/
3262 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3264 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3265 goto errorTreeReturn;
3268 /* if they are both literal then */
3269 /* rewrite the tree */
3270 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3272 tree->type = EX_VALUE;
3273 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3274 valFromType (RETYPE (tree)));
3275 tree->right = tree->left = NULL;
3276 TETYPE (tree) = getSpec (TTYPE (tree) =
3277 tree->opval.val->type);
3281 /* if left is a literal exchange left & right */
3282 if (IS_LITERAL (LTYPE (tree)))
3284 ast *tTree = tree->left;
3285 tree->left = tree->right;
3286 tree->right = tTree;
3289 /* if right is a literal and */
3290 /* we can find a 2nd literal in a mul-tree then */
3291 /* rearrange the tree */
3292 if (IS_LITERAL (RTYPE (tree)))
3295 ast *litTree = searchLitOp (tree, &parent, "*");
3299 ast *tTree = litTree->left;
3300 litTree->left = tree->right;
3301 tree->right = tTree;
3302 /* both operands in litTree are literal now */
3303 decorateType (parent, resultType);
3307 LRVAL (tree) = RRVAL (tree) = 1;
3308 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3309 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3310 TETYPE (tree) = getSpec (TTYPE (tree) =
3311 computeType (LTYPE (tree),
3318 /*------------------------------------------------------------------*/
3319 /*----------------------------*/
3320 /* unary '+' operator */
3321 /*----------------------------*/
3326 if (!IS_ARITHMETIC (LTYPE (tree)))
3328 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3329 goto errorTreeReturn;
3332 /* if left is a literal then do it */
3333 if (IS_LITERAL (LTYPE (tree)))
3335 tree->type = EX_VALUE;
3336 tree->opval.val = valFromType (LETYPE (tree));
3338 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3342 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3346 /*------------------------------------------------------------------*/
3347 /*----------------------------*/
3349 /*----------------------------*/
3351 /* this is not a unary operation */
3352 /* if both pointers then problem */
3353 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3354 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3356 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3357 goto errorTreeReturn;
3360 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3361 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3363 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3364 goto errorTreeReturn;
3367 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3368 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3370 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3371 goto errorTreeReturn;
3373 /* if they are both literal then */
3374 /* rewrite the tree */
3375 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3377 tree->type = EX_VALUE;
3378 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3379 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3380 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3381 valFromType (RETYPE (tree)));
3382 tree->right = tree->left = NULL;
3383 TETYPE (tree) = getSpec (TTYPE (tree) =
3384 tree->opval.val->type);
3388 /* if the right is a pointer or left is a literal
3389 xchange left & right */
3390 if (IS_ARRAY (RTYPE (tree)) ||
3391 IS_PTR (RTYPE (tree)) ||
3392 IS_LITERAL (LTYPE (tree)))
3394 ast *tTree = tree->left;
3395 tree->left = tree->right;
3396 tree->right = tTree;
3399 /* if right is a literal and */
3400 /* left is also an addition/subtraction with a literal then */
3401 /* rearrange the tree */
3402 if (IS_LITERAL (RTYPE (tree)))
3404 ast *litTree, *parent;
3405 litTree = searchLitOp (tree, &parent, "+-");
3408 if (litTree->opval.op == '+')
3412 ast *tTree = litTree->left;
3413 litTree->left = tree->right;
3414 tree->right = tree->left;
3417 else if (litTree->opval.op == '-')
3419 if (IS_LITERAL (RTYPE (litTree)))
3423 ast *tTree = litTree->left;
3424 litTree->left = tree->right;
3425 tree->right = tTree;
3431 ast *tTree = litTree->right;
3432 litTree->right = tree->right;
3433 tree->right = tTree;
3434 litTree->opval.op = '+';
3435 tree->opval.op = '-';
3438 decorateType (parent, resultType);
3442 LRVAL (tree) = RRVAL (tree) = 1;
3443 /* if the left is a pointer */
3444 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3445 TETYPE (tree) = getSpec (TTYPE (tree) =
3449 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3450 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3451 TETYPE (tree) = getSpec (TTYPE (tree) =
3452 computeType (LTYPE (tree),
3460 /*------------------------------------------------------------------*/
3461 /*----------------------------*/
3463 /*----------------------------*/
3464 case '-': /* can be unary */
3465 /* if right is null then unary */
3469 if (!IS_ARITHMETIC (LTYPE (tree)))
3471 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3472 goto errorTreeReturn;
3475 /* if left is a literal then do it */
3476 if (IS_LITERAL (LTYPE (tree)))
3478 tree->type = EX_VALUE;
3479 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3481 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3484 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3485 TETYPE (tree) = getSpec (TTYPE (tree) =
3486 computeType (LTYPE (tree),
3494 /*------------------------------------------------------------------*/
3495 /*----------------------------*/
3497 /*----------------------------*/
3499 if (!(IS_PTR (LTYPE (tree)) ||
3500 IS_ARRAY (LTYPE (tree)) ||
3501 IS_ARITHMETIC (LTYPE (tree))))
3503 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3504 goto errorTreeReturn;
3507 if (!(IS_PTR (RTYPE (tree)) ||
3508 IS_ARRAY (RTYPE (tree)) ||
3509 IS_ARITHMETIC (RTYPE (tree))))
3511 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3512 goto errorTreeReturn;
3515 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3516 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3517 IS_INTEGRAL (RTYPE (tree))))
3519 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3520 goto errorTreeReturn;
3523 /* if they are both literal then */
3524 /* rewrite the tree */
3525 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3527 tree->type = EX_VALUE;
3528 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3529 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3530 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3531 valFromType (RETYPE (tree)));
3532 tree->right = tree->left = NULL;
3533 TETYPE (tree) = getSpec (TTYPE (tree) =
3534 tree->opval.val->type);
3538 /* if the left & right are equal then zero */
3539 if (isAstEqual (tree->left, tree->right))
3541 tree->type = EX_VALUE;
3542 tree->left = tree->right = NULL;
3543 tree->opval.val = constCharVal (0);
3544 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3548 /* if both of them are pointers or arrays then */
3549 /* the result is going to be an integer */
3550 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3551 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3552 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3554 /* if only the left is a pointer */
3555 /* then result is a pointer */
3556 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3557 TETYPE (tree) = getSpec (TTYPE (tree) =
3561 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3562 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3564 TETYPE (tree) = getSpec (TTYPE (tree) =
3565 computeType (LTYPE (tree),
3571 LRVAL (tree) = RRVAL (tree) = 1;
3573 /* if right is a literal and */
3574 /* left is also an addition/subtraction with a literal then */
3575 /* rearrange the tree */
3576 if (IS_LITERAL (RTYPE (tree))
3577 /* avoid infinite loop */
3578 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3580 ast *litTree, *litParent;
3581 litTree = searchLitOp (tree, &litParent, "+-");
3584 if (litTree->opval.op == '+')
3588 ast *tTree = litTree->left;
3589 litTree->left = litTree->right;
3590 litTree->right = tree->right;
3591 tree->right = tTree;
3592 tree->opval.op = '+';
3593 litTree->opval.op = '-';
3595 else if (litTree->opval.op == '-')
3597 if (IS_LITERAL (RTYPE (litTree)))
3601 ast *tTree = litTree->left;
3602 litTree->left = tree->right;
3603 tree->right = litParent->left;
3604 litParent->left = tTree;
3605 litTree->opval.op = '+';
3607 tree->decorated = 0;
3608 decorateType (tree, resultType);
3614 ast *tTree = litTree->right;
3615 litTree->right = tree->right;
3616 tree->right = tTree;
3619 decorateType (litParent, resultType);
3624 /*------------------------------------------------------------------*/
3625 /*----------------------------*/
3627 /*----------------------------*/
3629 /* can be only integral type */
3630 if (!IS_INTEGRAL (LTYPE (tree)))
3632 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3633 goto errorTreeReturn;
3636 /* if left is a literal then do it */
3637 if (IS_LITERAL (LTYPE (tree)))
3639 tree->type = EX_VALUE;
3640 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3642 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3643 return addCast (tree, resultTypeProp, TRUE);
3646 if (resultType == RESULT_TYPE_BIT &&
3647 IS_UNSIGNED (tree->left->etype) &&
3648 getSize (tree->left->etype) < INTSIZE)
3650 /* promotion rules are responsible for this strange result:
3651 bit -> int -> ~int -> bit
3652 uchar -> int -> ~int -> bit
3654 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3656 /* optimize bit-result, even if we optimize a buggy source */
3657 tree->type = EX_VALUE;
3658 tree->opval.val = constCharVal (1);
3661 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3663 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3666 /*------------------------------------------------------------------*/
3667 /*----------------------------*/
3669 /*----------------------------*/
3671 /* can be pointer */
3672 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3673 !IS_PTR (LTYPE (tree)) &&
3674 !IS_ARRAY (LTYPE (tree)))
3676 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3677 goto errorTreeReturn;
3680 /* if left is another '!' */
3681 if (IS_AST_NOT_OPER (tree->left))
3683 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3685 /* replace double '!!X' by 'X' */
3686 return tree->left->left;
3688 /* remove double '!!X' by 'X ? 1 : 0' */
3689 tree->opval.op = '?';
3690 tree->left = tree->left->left;
3691 tree->right = newNode (':',
3692 newAst_VALUE (constCharVal (1)),
3693 newAst_VALUE (constCharVal (0)));
3694 tree->right->filename = tree->filename;
3695 tree->right->lineno = tree->lineno;
3696 tree->decorated = 0;
3697 return decorateType (tree, resultType);
3700 /* if left is a literal then do it */
3701 if (IS_LITERAL (LTYPE (tree)))
3703 tree->type = EX_VALUE;
3704 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3706 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3710 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3713 /*------------------------------------------------------------------*/
3714 /*----------------------------*/
3716 /*----------------------------*/
3720 TTYPE (tree) = LTYPE (tree);
3721 TETYPE (tree) = LETYPE (tree);
3726 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3730 TTYPE (tree) = TETYPE (tree) = newCharLink();
3734 TTYPE (tree) = TETYPE (tree) = newIntLink();
3739 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3741 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3742 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3743 printTypeChain (LTYPE (tree), stderr);
3744 fprintf (stderr, ",");
3745 printTypeChain (RTYPE (tree), stderr);
3746 fprintf (stderr, "\n");
3747 goto errorTreeReturn;
3750 /* make smaller type only if it's a LEFT_OP */
3751 if (tree->opval.op == LEFT_OP)
3752 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3754 /* if they are both literal then */
3755 /* rewrite the tree */
3756 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3758 tree->type = EX_VALUE;
3759 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3760 valFromType (RETYPE (tree)),
3761 (tree->opval.op == LEFT_OP ? 1 : 0));
3762 tree->right = tree->left = NULL;
3763 TETYPE (tree) = getSpec (TTYPE (tree) =
3764 tree->opval.val->type);
3768 /* see if this is a GETBYTE operation if yes
3771 ast *otree = optimizeGetByte (tree, resultType);
3774 return decorateType (otree, RESULT_TYPE_NONE);
3777 /* see if this is a GETWORD operation if yes
3780 ast *otree = optimizeGetWord (tree, resultType);
3783 return decorateType (otree, RESULT_TYPE_NONE);
3786 LRVAL (tree) = RRVAL (tree) = 1;
3787 if (tree->opval.op == LEFT_OP)
3789 TETYPE (tree) = getSpec (TTYPE (tree) =
3790 computeType (LTYPE (tree),
3797 /* no promotion necessary */
3798 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3799 if (IS_LITERAL (TTYPE (tree)))
3800 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3803 /* if only the right side is a literal & we are
3804 shifting more than size of the left operand then zero */
3805 if (IS_LITERAL (RTYPE (tree)) &&
3806 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3807 (getSize (TETYPE (tree)) * 8))
3809 if (tree->opval.op==LEFT_OP ||
3810 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3812 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3813 (tree->opval.op == LEFT_OP ? "left" : "right"));
3814 tree->type = EX_VALUE;
3815 tree->left = tree->right = NULL;
3816 tree->opval.val = constCharVal (0);
3817 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3824 /*------------------------------------------------------------------*/
3825 /*----------------------------*/
3827 /*----------------------------*/
3828 case CAST: /* change the type */
3829 /* cannot cast to an aggregate type */
3830 if (IS_AGGREGATE (LTYPE (tree)))
3832 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3833 goto errorTreeReturn;
3836 /* make sure the type is complete and sane */
3837 changePointer(LTYPE(tree));
3838 checkTypeSanity(LETYPE(tree), "(cast)");
3841 /* if 'from' and 'to' are the same remove the superfluous cast,
3842 * this helps other optimizations */
3843 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3845 /* mark that the explicit cast has been removed,
3846 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3847 tree->right->values.removedCast = 1;
3851 /* If code memory is read only, then pointers to code memory */
3852 /* implicitly point to constants -- make this explicit */
3854 sym_link *t = LTYPE(tree);
3855 while (t && t->next)
3857 if (IS_CODEPTR(t) && port->mem.code_ro)
3859 if (IS_SPEC(t->next))
3860 SPEC_CONST (t->next) = 1;
3862 DCL_PTR_CONST (t->next) = 1;
3869 /* if the right is a literal replace the tree */
3870 if (IS_LITERAL (RETYPE (tree))) {
3871 if (!IS_PTR (LTYPE (tree))) {
3872 tree->type = EX_VALUE;
3874 valCastLiteral (LTYPE (tree),
3875 floatFromVal (valFromType (RETYPE (tree))));
3878 TTYPE (tree) = tree->opval.val->type;
3879 tree->values.literalFromCast = 1;
3880 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3881 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3882 sym_link *rest = LTYPE(tree)->next;
3883 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3884 TTYPE(tree) = newLink(DECLARATOR);
3885 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3886 TTYPE(tree)->next = rest;
3887 tree->left->opval.lnk = TTYPE(tree);
3890 TTYPE (tree) = LTYPE (tree);
3894 TTYPE (tree) = LTYPE (tree);
3898 #if 0 // this is already checked, now this could be explicit
3899 /* if pointer to struct then check names */
3900 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3901 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3902 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3904 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3905 SPEC_STRUCT(LETYPE(tree))->tag);
3908 if (IS_ADDRESS_OF_OP(tree->right)
3909 && IS_AST_SYM_VALUE (tree->right->left)
3910 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3912 symbol * sym = AST_SYMBOL (tree->right->left);
3913 unsigned int gptype = 0;
3914 unsigned int addr = SPEC_ADDR (sym->etype);
3916 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3917 || TARGET_IS_PIC16) )
3919 switch (SPEC_SCLS (sym->etype))
3922 gptype = GPTYPE_CODE;
3925 gptype = GPTYPE_FAR;
3929 gptype = GPTYPE_NEAR;
3932 gptype = GPTYPE_XSTACK;
3937 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3938 gptype = GPTYPE_NEAR;
3940 addr |= gptype << (8*(GPTRSIZE - 1));
3943 tree->type = EX_VALUE;
3945 valCastLiteral (LTYPE (tree), addr);
3946 TTYPE (tree) = tree->opval.val->type;
3947 TETYPE (tree) = getSpec (TTYPE (tree));
3950 tree->values.literalFromCast = 1;
3954 /* handle offsetof macro: */
3955 /* #define offsetof(TYPE, MEMBER) \ */
3956 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3957 if (IS_ADDRESS_OF_OP(tree->right)
3958 && IS_AST_OP (tree->right->left)
3959 && tree->right->left->opval.op == PTR_OP
3960 && IS_AST_OP (tree->right->left->left)
3961 && tree->right->left->left->opval.op == CAST
3962 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3964 symbol *element = getStructElement (
3965 SPEC_STRUCT (LETYPE(tree->right->left)),
3966 AST_SYMBOL(tree->right->left->right)
3970 tree->type = EX_VALUE;
3971 tree->opval.val = valCastLiteral (
3974 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3977 TTYPE (tree) = tree->opval.val->type;
3978 TETYPE (tree) = getSpec (TTYPE (tree));
3985 /* if the right is a literal replace the tree */
3986 if (IS_LITERAL (RETYPE (tree))) {
3988 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3989 /* rewrite (type *)litaddr
3991 and define type at litaddr temp
3992 (but only if type's storage class is not generic)
3994 ast *newTree = newNode ('&', NULL, NULL);
3997 TTYPE (newTree) = LTYPE (tree);
3998 TETYPE (newTree) = getSpec(LTYPE (tree));
4000 /* define a global symbol at the casted address*/
4001 sym = newSymbol(genSymName (0), 0);
4002 sym->type = LTYPE (tree)->next;
4004 sym->type = newLink (V_VOID);
4005 sym->etype = getSpec(sym->type);
4006 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4007 sym->lineDef = tree->lineno;
4010 SPEC_STAT (sym->etype) = 1;
4011 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4012 SPEC_ABSA(sym->etype) = 1;
4013 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4016 newTree->left = newAst_VALUE(symbolVal(sym));
4017 newTree->left->filename = tree->filename;
4018 newTree->left->lineno = tree->lineno;
4019 LTYPE (newTree) = sym->type;
4020 LETYPE (newTree) = sym->etype;
4021 LLVAL (newTree) = 1;
4022 LRVAL (newTree) = 0;
4023 TLVAL (newTree) = 1;
4027 if (!IS_PTR (LTYPE (tree))) {
4028 tree->type = EX_VALUE;
4030 valCastLiteral (LTYPE (tree),
4031 floatFromVal (valFromType (RTYPE (tree))));
4032 TTYPE (tree) = tree->opval.val->type;
4035 tree->values.literalFromCast = 1;
4036 TETYPE (tree) = getSpec (TTYPE (tree));
4040 TTYPE (tree) = LTYPE (tree);
4044 TETYPE (tree) = getSpec (TTYPE (tree));
4048 /*------------------------------------------------------------------*/
4049 /*----------------------------*/
4050 /* logical &&, || */
4051 /*----------------------------*/
4054 /* each must be arithmetic type or be a pointer */
4055 if (!IS_PTR (LTYPE (tree)) &&
4056 !IS_ARRAY (LTYPE (tree)) &&
4057 !IS_INTEGRAL (LTYPE (tree)))
4059 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4060 goto errorTreeReturn;
4063 if (!IS_PTR (RTYPE (tree)) &&
4064 !IS_ARRAY (RTYPE (tree)) &&
4065 !IS_INTEGRAL (RTYPE (tree)))
4067 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4068 goto errorTreeReturn;
4070 /* if they are both literal then */
4071 /* rewrite the tree */
4072 if (IS_LITERAL (RTYPE (tree)) &&
4073 IS_LITERAL (LTYPE (tree)))
4075 tree->type = EX_VALUE;
4076 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4077 valFromType (RTYPE (tree)),
4079 tree->right = tree->left = NULL;
4080 TETYPE (tree) = getSpec (TTYPE (tree) =
4081 tree->opval.val->type);
4084 LRVAL (tree) = RRVAL (tree) = 1;
4085 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4088 /*------------------------------------------------------------------*/
4089 /*----------------------------*/
4090 /* comparison operators */
4091 /*----------------------------*/
4099 ast *lt = optimizeCompare (tree);
4105 /* if they are pointers they must be castable */
4106 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4108 if (tree->opval.op==EQ_OP &&
4109 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4110 // we cannot cast a gptr to a !gptr: switch the leaves
4111 struct ast *s=tree->left;
4112 tree->left=tree->right;
4115 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4117 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4118 fprintf (stderr, "comparing type ");
4119 printTypeChain (LTYPE (tree), stderr);
4120 fprintf (stderr, "to type ");
4121 printTypeChain (RTYPE (tree), stderr);
4122 fprintf (stderr, "\n");
4123 goto errorTreeReturn;
4126 /* else they should be promotable to one another */
4129 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4130 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4132 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4134 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4135 fprintf (stderr, "comparing type ");
4136 printTypeChain (LTYPE (tree), stderr);
4137 fprintf (stderr, "to type ");
4138 printTypeChain (RTYPE (tree), stderr);
4139 fprintf (stderr, "\n");
4140 goto errorTreeReturn;
4145 CCR_RESULT ccr_result = CCR_OK;
4147 /* if left is integral and right is literal
4148 then check constant range */
4149 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4150 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4151 tree->opval.op, FALSE);
4152 if (ccr_result == CCR_OK &&
4153 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4154 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4155 tree->opval.op, TRUE);
4158 case CCR_ALWAYS_TRUE:
4159 case CCR_ALWAYS_FALSE:
4160 if (!options.lessPedantic)
4161 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4162 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4163 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4170 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4171 if (tree->opval.op == '>' &&
4172 SPEC_USIGN(LETYPE(tree)) &&
4173 IS_LITERAL(RTYPE(tree)) &&
4174 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4176 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4178 /* the parent is an ifx: */
4179 /* if (unsigned value) */
4183 /* (unsigned value) ? 1 : 0 */
4184 tree->opval.op = '?';
4185 tree->right = newNode (':',
4186 newAst_VALUE (constCharVal (1)),
4187 tree->right); /* val 0 */
4188 tree->right->filename = tree->filename;
4189 tree->right->lineno = tree->lineno;
4190 tree->right->left->filename = tree->filename;
4191 tree->right->left->lineno = tree->lineno;
4192 tree->decorated = 0;
4193 return decorateType (tree, resultType);
4196 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4197 if (IS_LITERAL(RTYPE(tree)) &&
4198 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4199 tree->opval.op == EQ_OP &&
4200 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4202 tree->opval.op = '!';
4204 tree->decorated = 0;
4205 return decorateType (tree, resultType);
4208 /* if they are both literal then */
4209 /* rewrite the tree */
4210 if (IS_LITERAL (RTYPE (tree)) &&
4211 IS_LITERAL (LTYPE (tree)))
4213 tree->type = EX_VALUE;
4214 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4215 valFromType (RETYPE (tree)),
4217 tree->right = tree->left = NULL;
4218 TETYPE (tree) = getSpec (TTYPE (tree) =
4219 tree->opval.val->type);
4223 /* if one is 'signed char ' and the other one is 'unsigned char' */
4224 /* it's necessary to promote to int */
4225 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4226 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4228 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4229 if it's possible to use a 'signed char' */
4231 /* is left a 'unsigned char'? */
4232 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4233 /* the value range of a 'unsigned char' is 0...255;
4234 if the actual value is < 128 it can be changed to signed */
4235 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4237 /* now we've got 2 'signed char'! */
4238 SPEC_USIGN (RETYPE (tree)) = 0;
4240 /* same test for the left operand: */
4241 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4242 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4244 SPEC_USIGN (LETYPE (tree)) = 0;
4248 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4249 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4250 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4254 LRVAL (tree) = RRVAL (tree) = 1;
4255 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4257 /* condition transformations */
4259 unsigned transformedOp = 0;
4261 switch (tree->opval.op)
4263 case '<': /* transform (a < b) to !(a >= b) */
4265 transformedOp = GE_OP;
4267 case '>': /* transform (a > b) to !(a <= b) */
4269 transformedOp = LE_OP;
4271 case LE_OP: /* transform (a <= b) to !(a > b) */
4273 transformedOp = '>';
4275 case GE_OP: /* transform (a >= b) to !(a < b) */
4277 transformedOp = '<';
4279 case NE_OP: /* transform (a != b) to !(a == b) */
4281 transformedOp = EQ_OP;
4283 case EQ_OP: /* transform (a == b) to !(a != b) */
4285 transformedOp = NE_OP;
4292 tree->opval.op = transformedOp;
4293 tree->decorated = 0;
4294 tree = newNode ('!', tree, NULL);
4295 tree->filename = tree->left->filename;
4296 tree->lineno = tree->left->lineno;
4297 return decorateType (tree, resultType);
4303 /*------------------------------------------------------------------*/
4304 /*----------------------------*/
4306 /*----------------------------*/
4307 case SIZEOF: /* evaluate wihout code generation */
4308 /* change the type to a integer */
4310 int size = getSize (tree->right->ftype);
4312 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4313 if (!size && !IS_VOID(tree->right->ftype))
4314 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4316 tree->type = EX_VALUE;
4317 tree->opval.val = constVal (buffer);
4318 tree->right = tree->left = NULL;
4319 TETYPE (tree) = getSpec (TTYPE (tree) =
4320 tree->opval.val->type);
4324 /*------------------------------------------------------------------*/
4325 /*----------------------------*/
4327 /*----------------------------*/
4329 /* return typeof enum value */
4330 tree->type = EX_VALUE;
4333 if (IS_SPEC(tree->right->ftype)) {
4334 switch (SPEC_NOUN(tree->right->ftype)) {
4336 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4337 else typeofv = TYPEOF_INT;
4340 typeofv = TYPEOF_FLOAT;
4343 typeofv = TYPEOF_FIXED16X16;
4346 typeofv = TYPEOF_CHAR;
4349 typeofv = TYPEOF_VOID;
4352 typeofv = TYPEOF_STRUCT;
4355 typeofv = TYPEOF_BITFIELD;
4358 typeofv = TYPEOF_BIT;
4361 typeofv = TYPEOF_SBIT;
4367 switch (DCL_TYPE(tree->right->ftype)) {
4369 typeofv = TYPEOF_POINTER;
4372 typeofv = TYPEOF_FPOINTER;
4375 typeofv = TYPEOF_CPOINTER;
4378 typeofv = TYPEOF_GPOINTER;
4381 typeofv = TYPEOF_PPOINTER;
4384 typeofv = TYPEOF_IPOINTER;
4387 typeofv = TYPEOF_ARRAY;
4390 typeofv = TYPEOF_FUNCTION;
4396 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4397 tree->opval.val = constVal (buffer);
4398 tree->right = tree->left = NULL;
4399 TETYPE (tree) = getSpec (TTYPE (tree) =
4400 tree->opval.val->type);
4403 /*------------------------------------------------------------------*/
4404 /*----------------------------*/
4405 /* conditional operator '?' */
4406 /*----------------------------*/
4408 /* the type is value of the colon operator (on the right) */
4409 assert (IS_COLON_OP (tree->right));
4411 /* If already known then replace the tree : optimizer will do it
4412 but faster to do it here. If done before decorating tree->right
4413 this can save generating unused const strings. */
4414 if (IS_LITERAL (LTYPE (tree)))
4416 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4417 return decorateType (tree->right->left, resultTypeProp);
4419 return decorateType (tree->right->right, resultTypeProp);
4422 tree->right = decorateType (tree->right, resultTypeProp);
4424 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4425 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4427 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4428 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4430 if ((valTrue != 0) && (valFalse == 0))
4432 /* assign cond to result */
4433 tree->left->decorated = 0;
4434 return decorateType (tree->left, resultTypeProp);
4436 else if ((valTrue == 0) && (valFalse != 0))
4438 /* assign !cond to result */
4439 tree->opval.op = '!';
4440 tree->decorated = 0;
4442 return decorateType (tree, resultTypeProp);
4446 /* they have the same boolean value, make them equal */
4447 tree->right->left = tree->right->right;
4451 /* if they are equal then replace the tree */
4452 if (isAstEqual (tree->right->left, tree->right->right))
4454 return tree->right->left;
4457 TTYPE (tree) = RTYPE (tree);
4458 TETYPE (tree) = getSpec (TTYPE (tree));
4462 /* if they don't match we have a problem */
4463 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4464 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4466 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4467 goto errorTreeReturn;
4470 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4471 resultType, tree->opval.op);
4472 TETYPE (tree) = getSpec (TTYPE (tree));
4476 #if 0 // assignment operators are converted by the parser
4477 /*------------------------------------------------------------------*/
4478 /*----------------------------*/
4479 /* assignment operators */
4480 /*----------------------------*/
4483 /* for these it must be both must be integral */
4484 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4485 !IS_ARITHMETIC (RTYPE (tree)))
4487 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4488 goto errorTreeReturn;
4491 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4493 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4494 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4498 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4499 goto errorTreeReturn;
4510 /* for these it must be both must be integral */
4511 if (!IS_INTEGRAL (LTYPE (tree)) ||
4512 !IS_INTEGRAL (RTYPE (tree)))
4514 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4515 goto errorTreeReturn;
4518 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4520 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4521 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4525 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4526 goto errorTreeReturn;
4532 /*------------------------------------------------------------------*/
4533 /*----------------------------*/
4535 /*----------------------------*/
4537 if (!(IS_PTR (LTYPE (tree)) ||
4538 IS_ARITHMETIC (LTYPE (tree))))
4540 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4541 goto errorTreeReturn;
4544 if (!(IS_PTR (RTYPE (tree)) ||
4545 IS_ARITHMETIC (RTYPE (tree))))
4547 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4548 goto errorTreeReturn;
4551 TETYPE (tree) = getSpec (TTYPE (tree) =
4552 computeType (LTYPE (tree),
4557 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4558 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4562 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4563 goto errorTreeReturn;
4569 /*------------------------------------------------------------------*/
4570 /*----------------------------*/
4572 /*----------------------------*/
4574 /* this is not a unary operation */
4575 /* if both pointers then problem */
4576 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4578 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4579 goto errorTreeReturn;
4582 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4584 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4585 goto errorTreeReturn;
4588 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4590 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4591 goto errorTreeReturn;
4594 TETYPE (tree) = getSpec (TTYPE (tree) =
4595 computeType (LTYPE (tree),
4600 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4601 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4605 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4606 goto errorTreeReturn;
4609 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4610 tree->opval.op = '=';
4615 /*------------------------------------------------------------------*/
4616 /*----------------------------*/
4617 /* straight assignemnt */
4618 /*----------------------------*/
4620 /* cannot be an aggregate */
4621 if (IS_AGGREGATE (LTYPE (tree)))
4623 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4624 goto errorTreeReturn;
4627 /* they should either match or be castable */
4628 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4630 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4631 printFromToType(RTYPE(tree),LTYPE(tree));
4634 /* if the left side of the tree is of type void
4635 then report error */
4636 if (IS_VOID (LTYPE (tree)))
4638 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4639 printFromToType(RTYPE(tree), LTYPE(tree));
4642 TETYPE (tree) = getSpec (TTYPE (tree) =
4646 if (!tree->initMode ) {
4647 if (IS_CONSTANT(LTYPE(tree)))
4648 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4652 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4653 goto errorTreeReturn;
4658 /*------------------------------------------------------------------*/
4659 /*----------------------------*/
4660 /* comma operator */
4661 /*----------------------------*/
4663 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4666 /*------------------------------------------------------------------*/
4667 /*----------------------------*/
4669 /*----------------------------*/
4672 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4673 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4675 if (tree->left->opval.op == '*' && !tree->left->right)
4676 tree->left = tree->left->left;
4679 /* require a function or pointer to function */
4680 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4682 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4683 goto errorTreeReturn;
4686 /* if there are parms, make sure that
4687 parms are decorate / process / reverse only once */
4689 !tree->right->decorated)
4694 if (IS_FUNCPTR (LTYPE (tree)))
4696 functype = LTYPE (tree)->next;
4697 processFuncPtrArgs (functype);
4700 functype = LTYPE (tree);
4702 if (processParms (tree->left, FUNC_ARGS(functype),
4703 &tree->right, &parmNumber, TRUE))
4705 goto errorTreeReturn;
4708 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4709 !IFFUNC_ISBUILTIN(functype))
4711 reverseParms (tree->right);
4714 TTYPE (tree) = functype->next;
4715 TETYPE (tree) = getSpec (TTYPE (tree));
4719 /*------------------------------------------------------------------*/
4720 /*----------------------------*/
4721 /* return statement */
4722 /*----------------------------*/
4727 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4729 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4730 printFromToType (RTYPE(tree), currFunc->type->next);
4731 goto errorTreeReturn;
4734 if (IS_VOID (currFunc->type->next)
4736 !IS_VOID (RTYPE (tree)))
4738 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4739 goto errorTreeReturn;
4742 /* if there is going to be a casting required then add it */
4743 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4746 decorateType (newNode (CAST,
4747 newAst_LINK (copyLinkChain (currFunc->type->next)),
4757 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4759 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4760 goto errorTreeReturn;
4763 TTYPE (tree) = TETYPE (tree) = NULL;
4766 /*------------------------------------------------------------------*/
4767 /*----------------------------*/
4768 /* switch statement */
4769 /*----------------------------*/
4771 /* the switch value must be an integer */
4772 if (!IS_INTEGRAL (LTYPE (tree)))
4774 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4775 goto errorTreeReturn;
4778 TTYPE (tree) = TETYPE (tree) = NULL;
4781 /*------------------------------------------------------------------*/
4782 /*----------------------------*/
4784 /*----------------------------*/
4786 tree->left = backPatchLabels (tree->left,
4789 TTYPE (tree) = TETYPE (tree) = NULL;
4792 /*------------------------------------------------------------------*/
4793 /*----------------------------*/
4795 /*----------------------------*/
4798 AST_FOR (tree, initExpr) = decorateType (
4799 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4800 AST_FOR (tree, condExpr) = decorateType (
4801 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4802 AST_FOR (tree, loopExpr) = decorateType (
4803 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4805 /* if the for loop is reversible then
4806 reverse it otherwise do what we normally
4812 if (isLoopReversible (tree, &sym, &init, &end))
4813 return reverseLoop (tree, sym, init, end);
4815 return decorateType (createFor (AST_FOR (tree, trueLabel),
4816 AST_FOR (tree, continueLabel),
4817 AST_FOR (tree, falseLabel),
4818 AST_FOR (tree, condLabel),
4819 AST_FOR (tree, initExpr),
4820 AST_FOR (tree, condExpr),
4821 AST_FOR (tree, loopExpr),
4822 tree->left), RESULT_TYPE_NONE);
4825 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4826 "node PARAM shouldn't be processed here");
4827 /* but in processParams() */
4830 TTYPE (tree) = TETYPE (tree) = NULL;
4834 /* some error found this tree will be killed */
4836 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4837 tree->opval.op = NULLOP;
4843 /*-----------------------------------------------------------------*/
4844 /* sizeofOp - processes size of operation */
4845 /*-----------------------------------------------------------------*/
4847 sizeofOp (sym_link * type)
4852 /* make sure the type is complete and sane */
4853 checkTypeSanity(type, "(sizeof)");
4855 /* get the size and convert it to character */
4856 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4857 if (!size && !IS_VOID(type))
4858 werror (E_SIZEOF_INCOMPLETE_TYPE);
4860 /* now convert into value */
4861 return constVal (buff);
4865 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4866 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4867 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4868 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4869 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4870 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4871 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4873 /*-----------------------------------------------------------------*/
4874 /* backPatchLabels - change and or not operators to flow control */
4875 /*-----------------------------------------------------------------*/
4877 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4883 /* while-loops insert a label between the IFX and the condition,
4884 therefore look behind the label too */
4885 if (tree->opval.op == LABEL &&
4887 IS_ANDORNOT (tree->right))
4889 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4893 if (!(IS_ANDORNOT (tree)))
4896 /* if this an and */
4899 static int localLbl = 0;
4902 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4903 localLabel = newSymbol (buffer, NestLevel);
4905 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4907 /* if left is already a IFX then just change the if true label in that */
4908 if (!IS_IFX (tree->left))
4909 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4911 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4912 /* right is a IFX then just join */
4913 if (IS_IFX (tree->right))
4914 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4916 tree->right = createLabel (localLabel, tree->right);
4917 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4919 return newNode (NULLOP, tree->left, tree->right);
4922 /* if this is an or operation */
4925 static int localLbl = 0;
4928 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4929 localLabel = newSymbol (buffer, NestLevel);
4931 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4933 /* if left is already a IFX then just change the if true label in that */
4934 if (!IS_IFX (tree->left))
4935 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4937 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4938 /* right is a IFX then just join */
4939 if (IS_IFX (tree->right))
4940 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4942 tree->right = createLabel (localLabel, tree->right);
4943 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4945 return newNode (NULLOP, tree->left, tree->right);
4951 /* call with exchanged labels */
4952 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4954 /* if left isn't already a IFX */
4955 if (!IS_IFX (tree->left))
4957 tree->left = newNode (IFX, tree->left, NULL);
4958 tree->left->trueLabel = falseLabel;
4959 tree->left->falseLabel = trueLabel;
4966 tree->trueLabel = trueLabel;
4967 tree->falseLabel = falseLabel;
4974 /*-----------------------------------------------------------------*/
4975 /* createBlock - create expression tree for block */
4976 /*-----------------------------------------------------------------*/
4978 createBlock (symbol * decl, ast * body)
4982 /* if the block has nothing */
4986 ex = newNode (BLOCK, NULL, body);
4987 ex->values.sym = decl;
4990 ex->filename = NULL;
4995 /*-----------------------------------------------------------------*/
4996 /* createLabel - creates the expression tree for labels */
4997 /*-----------------------------------------------------------------*/
4999 createLabel (symbol * label, ast * stmnt)
5002 char name[SDCC_NAME_MAX + 1];
5005 /* must create fresh symbol if the symbol name */
5006 /* exists in the symbol table, since there can */
5007 /* be a variable with the same name as the labl */
5008 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5009 (csym->level == label->level))
5010 label = newSymbol (label->name, label->level);
5012 /* change the name before putting it in add _ */
5013 SNPRINTF(name, sizeof(name), "%s", label->name);
5015 /* put the label in the LabelSymbol table */
5016 /* but first check if a label of the same */
5018 if ((csym = findSym (LabelTab, NULL, name)))
5019 werror (E_DUPLICATE_LABEL, label->name);
5021 addSym (LabelTab, label, name, label->level, 0, 0);
5025 label->key = labelKey++;
5026 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5027 rValue->filename = NULL;
5033 /*-----------------------------------------------------------------*/
5034 /* createCase - generates the parsetree for a case statement */
5035 /*-----------------------------------------------------------------*/
5037 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5039 char caseLbl[SDCC_NAME_MAX + 1];
5043 /* if the switch statement does not exist */
5044 /* then case is out of context */
5047 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5051 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5052 /* if not a constant then error */
5053 if (!IS_LITERAL (caseVal->ftype))
5055 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5059 /* if not a integer than error */
5060 if (!IS_INTEGRAL (caseVal->ftype))
5062 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5066 /* find the end of the switch values chain */
5067 if (!(val = swStat->values.switchVals.swVals))
5068 swStat->values.switchVals.swVals = caseVal->opval.val;
5071 /* also order the cases according to value */
5073 int cVal = (int) ulFromVal (caseVal->opval.val);
5074 while (val && (int) ulFromVal (val) < cVal)
5080 /* if we reached the end then */
5083 pval->next = caseVal->opval.val;
5085 else if ((int) ulFromVal (val) == cVal)
5087 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5093 /* we found a value greater than */
5094 /* the current value we must add this */
5095 /* before the value */
5096 caseVal->opval.val->next = val;
5098 /* if this was the first in chain */
5099 if (swStat->values.switchVals.swVals == val)
5100 swStat->values.switchVals.swVals =
5103 pval->next = caseVal->opval.val;
5108 /* create the case label */
5109 SNPRINTF(caseLbl, sizeof(caseLbl),
5111 swStat->values.switchVals.swNum,
5112 (int) ulFromVal (caseVal->opval.val));
5114 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5115 rexpr->filename = 0;
5120 /*-----------------------------------------------------------------*/
5121 /* createDefault - creates the parse tree for the default statement */
5122 /*-----------------------------------------------------------------*/
5124 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5126 char defLbl[SDCC_NAME_MAX + 1];
5128 /* if the switch statement does not exist */
5129 /* then case is out of context */
5132 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5136 if (swStat->values.switchVals.swDefault)
5138 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5143 /* turn on the default flag */
5144 swStat->values.switchVals.swDefault = 1;
5146 /* create the label */
5147 SNPRINTF (defLbl, sizeof(defLbl),
5148 "_default_%d", swStat->values.switchVals.swNum);
5149 return createLabel (newSymbol (defLbl, 0), stmnt);
5152 /*-----------------------------------------------------------------*/
5153 /* createIf - creates the parsetree for the if statement */
5154 /*-----------------------------------------------------------------*/
5156 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5158 static int Lblnum = 0;
5160 symbol *ifTrue, *ifFalse, *ifEnd;
5162 /* if neither exists */
5163 if (!elseBody && !ifBody) {
5164 // if there are no side effects (i++, j() etc)
5165 if (!hasSEFcalls(condAst)) {
5170 /* create the labels */
5171 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5172 ifFalse = newSymbol (buffer, NestLevel);
5173 /* if no else body then end == false */
5178 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5179 ifEnd = newSymbol (buffer, NestLevel);
5182 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5183 ifTrue = newSymbol (buffer, NestLevel);
5187 /* attach the ifTrue label to the top of it body */
5188 ifBody = createLabel (ifTrue, ifBody);
5189 /* attach a goto end to the ifBody if else is present */
5192 ifBody = newNode (NULLOP, ifBody,
5194 newAst_VALUE (symbolVal (ifEnd)),
5196 /* put the elseLabel on the else body */
5197 elseBody = createLabel (ifFalse, elseBody);
5198 /* out the end at the end of the body */
5199 elseBody = newNode (NULLOP,
5201 createLabel (ifEnd, NULL));
5205 ifBody = newNode (NULLOP, ifBody,
5206 createLabel (ifFalse, NULL));
5208 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5209 if (IS_IFX (condAst))
5212 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5214 return newNode (NULLOP, ifTree,
5215 newNode (NULLOP, ifBody, elseBody));
5219 /*-----------------------------------------------------------------*/
5220 /* createDo - creates parse tree for do */
5223 /* _docontinue_n: */
5224 /* condition_expression +-> trueLabel -> _dobody_n */
5226 /* +-> falseLabel-> _dobreak_n */
5228 /*-----------------------------------------------------------------*/
5230 createDo (symbol * trueLabel, symbol * continueLabel,
5231 symbol * falseLabel, ast * condAst, ast * doBody)
5236 /* if the body does not exist then it is simple */
5239 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5240 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5241 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5242 doTree->trueLabel = continueLabel;
5243 doTree->falseLabel = NULL;
5245 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5249 /* otherwise we have a body */
5250 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5252 /* attach the body label to the top */
5253 doBody = createLabel (trueLabel, doBody);
5254 /* attach the continue label to end of body */
5255 doBody = newNode (NULLOP, doBody,
5256 createLabel (continueLabel, NULL));
5258 /* now put the break label at the end */
5259 if (IS_IFX (condAst))
5262 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5264 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5266 /* putting it together */
5267 return newNode (NULLOP, doBody, doTree);
5270 /*-----------------------------------------------------------------*/
5271 /* createFor - creates parse tree for 'for' statement */
5274 /* condExpr +-> trueLabel -> _forbody_n */
5276 /* +-> falseLabel-> _forbreak_n */
5279 /* _forcontinue_n: */
5281 /* goto _forcond_n ; */
5283 /*-----------------------------------------------------------------*/
5285 createFor (symbol * trueLabel, symbol * continueLabel,
5286 symbol * falseLabel, symbol * condLabel,
5287 ast * initExpr, ast * condExpr, ast * loopExpr,
5292 /* if loopexpression not present then we can generate it */
5293 /* the same way as a while */
5295 return newNode (NULLOP, initExpr,
5296 createWhile (trueLabel, continueLabel,
5297 falseLabel, condExpr, forBody));
5298 /* vanilla for statement */
5299 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5301 if (condExpr && !IS_IFX (condExpr))
5302 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5305 /* attach condition label to condition */
5306 condExpr = createLabel (condLabel, condExpr);
5308 /* attach body label to body */
5309 forBody = createLabel (trueLabel, forBody);
5311 /* attach continue to forLoop expression & attach */
5312 /* goto the forcond @ and of loopExpression */
5313 loopExpr = createLabel (continueLabel,
5317 newAst_VALUE (symbolVal (condLabel)),
5319 /* now start putting them together */
5320 forTree = newNode (NULLOP, initExpr, condExpr);
5321 forTree = newNode (NULLOP, forTree, forBody);
5322 forTree = newNode (NULLOP, forTree, loopExpr);
5323 /* finally add the break label */
5324 forTree = newNode (NULLOP, forTree,
5325 createLabel (falseLabel, NULL));
5329 /*-----------------------------------------------------------------*/
5330 /* createWhile - creates parse tree for while statement */
5331 /* the while statement will be created as follows */
5333 /* _while_continue_n: */
5334 /* condition_expression +-> trueLabel -> _while_boby_n */
5336 /* +-> falseLabel -> _while_break_n */
5337 /* _while_body_n: */
5339 /* goto _while_continue_n */
5340 /* _while_break_n: */
5341 /*-----------------------------------------------------------------*/
5343 createWhile (symbol * trueLabel, symbol * continueLabel,
5344 symbol * falseLabel, ast * condExpr, ast * whileBody)
5348 /* put the continue label */
5349 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5350 condExpr = createLabel (continueLabel, condExpr);
5351 condExpr->filename = NULL;
5352 condExpr->lineno = 0;
5354 /* put the body label in front of the body */
5355 whileBody = createLabel (trueLabel, whileBody);
5356 whileBody->filename = NULL;
5357 whileBody->lineno = 0;
5358 /* put a jump to continue at the end of the body */
5359 /* and put break label at the end of the body */
5360 whileBody = newNode (NULLOP,
5363 newAst_VALUE (symbolVal (continueLabel)),
5364 createLabel (falseLabel, NULL)));
5366 /* put it all together */
5367 if (IS_IFX (condExpr))
5368 whileTree = condExpr;
5371 whileTree = newNode (IFX, condExpr, NULL);
5372 /* put the true & false labels in place */
5373 whileTree->trueLabel = trueLabel;
5374 whileTree->falseLabel = falseLabel;
5377 return newNode (NULLOP, whileTree, whileBody);
5380 /*-----------------------------------------------------------------*/
5381 /* isShiftRightLitVal _BitAndLitVal - helper function */
5382 /*-----------------------------------------------------------------*/
5384 isShiftRightLitVal_BitAndLitVal (ast * tree)
5386 /* if this is not a bit and */
5387 if (!IS_BITAND (tree))
5390 /* will look for tree of the form
5391 ( expr >> litval2) & litval1 */
5392 if (!IS_AST_LIT_VALUE (tree->right))
5395 if (!IS_RIGHT_OP (tree->left))
5398 if (!IS_AST_LIT_VALUE (tree->left->right))
5401 return tree->left->left;
5404 /*-----------------------------------------------------------------*/
5405 /* isBitAndPowOf2 - helper function */
5406 /*-----------------------------------------------------------------*/
5408 isBitAndPow2 (ast * tree)
5410 /* if this is not a bit and */
5411 if (!IS_BITAND (tree))
5414 /* will look for tree of the form
5415 ( expr & (1 << litval) */
5416 if (!IS_AST_LIT_VALUE (tree->right))
5419 return powof2 (AST_ULONG_VALUE (tree->right));
5422 /*-----------------------------------------------------------------*/
5423 /* optimizeGetHbit - get highest order bit of the expression */
5424 /*-----------------------------------------------------------------*/
5426 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5431 expr = isShiftRightLitVal_BitAndLitVal(tree);
5434 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5435 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5436 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5439 if (!expr && (resultType == RESULT_TYPE_BIT))
5442 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5448 /* make sure the port supports GETHBIT */
5449 if (port->hasExtBitOp
5450 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5453 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5456 /*-----------------------------------------------------------------*/
5457 /* optimizeGetAbit - get a single bit of the expression */
5458 /*-----------------------------------------------------------------*/
5460 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5465 expr = isShiftRightLitVal_BitAndLitVal(tree);
5468 if (AST_ULONG_VALUE (tree->right) != 1)
5470 count = tree->left->right;
5472 if (!expr && (resultType == RESULT_TYPE_BIT))
5474 int p2 = isBitAndPow2 (tree);
5478 count = newAst_VALUE (valueFromLit (p2));
5484 /* make sure the port supports GETABIT */
5485 if (port->hasExtBitOp
5486 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5489 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5493 /*-----------------------------------------------------------------*/
5494 /* optimizeGetByte - get a byte of the expression */
5495 /*-----------------------------------------------------------------*/
5497 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5503 expr = isShiftRightLitVal_BitAndLitVal(tree);
5506 i = AST_ULONG_VALUE (tree->left->right);
5507 count = tree->left->right;
5508 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5511 if (!expr && resultType == RESULT_TYPE_CHAR)
5513 /* if this is a right shift over a multiple of 8 */
5514 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5516 i = AST_ULONG_VALUE (tree->right);
5517 count = tree->right;
5521 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5524 /* make sure the port supports GETBYTE */
5525 if (port->hasExtBitOp
5526 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5529 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5532 /*-----------------------------------------------------------------*/
5533 /* optimizeGetWord - get two bytes of the expression */
5534 /*-----------------------------------------------------------------*/
5536 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5542 expr = isShiftRightLitVal_BitAndLitVal(tree);
5545 i = AST_ULONG_VALUE (tree->left->right);
5546 count = tree->left->right;
5547 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5550 if (!expr && resultType == RESULT_TYPE_INT)
5552 /* if this is a right shift over a multiple of 8 */
5553 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5555 i = AST_ULONG_VALUE (tree->right);
5556 count = tree->right;
5560 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5563 /* make sure the port supports GETWORD */
5564 if (port->hasExtBitOp
5565 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5568 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5571 /*-----------------------------------------------------------------*/
5572 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5573 /*-----------------------------------------------------------------*/
5575 optimizeRRCRLC (ast * root)
5577 /* will look for trees of the form
5578 (?expr << 1) | (?expr >> 7) or
5579 (?expr >> 7) | (?expr << 1) will make that
5580 into a RLC : operation ..
5582 (?expr >> 1) | (?expr << 7) or
5583 (?expr << 7) | (?expr >> 1) will make that
5584 into a RRC operation
5585 note : by 7 I mean (number of bits required to hold the
5587 /* if the root operation is not a | operation then not */
5588 if (!IS_BITOR (root))
5591 /* I have to think of a better way to match patterns this sucks */
5592 /* that aside let's start looking for the first case : I use a
5593 negative check a lot to improve the efficiency */
5594 /* (?expr << 1) | (?expr >> 7) */
5595 if (IS_LEFT_OP (root->left) &&
5596 IS_RIGHT_OP (root->right))
5599 if (!SPEC_USIGN (TETYPE (root->left->left)))
5602 if (!IS_AST_LIT_VALUE (root->left->right) ||
5603 !IS_AST_LIT_VALUE (root->right->right))
5606 /* make sure it is the same expression */
5607 if (!isAstEqual (root->left->left,
5611 if (AST_ULONG_VALUE (root->left->right) != 1)
5614 if (AST_ULONG_VALUE (root->right->right) !=
5615 (getSize (TTYPE (root->left->left)) * 8 - 1))
5618 /* make sure the port supports RLC */
5619 if (port->hasExtBitOp
5620 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5623 /* whew got the first case : create the AST */
5624 return newNode (RLC, root->left->left, NULL);
5628 /* check for second case */
5629 /* (?expr >> 7) | (?expr << 1) */
5630 if (IS_LEFT_OP (root->right) &&
5631 IS_RIGHT_OP (root->left))
5634 if (!SPEC_USIGN (TETYPE (root->left->left)))
5637 if (!IS_AST_LIT_VALUE (root->left->right) ||
5638 !IS_AST_LIT_VALUE (root->right->right))
5641 /* make sure it is the same symbol */
5642 if (!isAstEqual (root->left->left,
5646 if (AST_ULONG_VALUE (root->right->right) != 1)
5649 if (AST_ULONG_VALUE (root->left->right) !=
5650 (getSize (TTYPE (root->left->left)) * 8 - 1))
5653 /* make sure the port supports RLC */
5654 if (port->hasExtBitOp
5655 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5658 /* whew got the first case : create the AST */
5659 return newNode (RLC, root->left->left, NULL);
5664 /* third case for RRC */
5665 /* (?symbol >> 1) | (?symbol << 7) */
5666 if (IS_LEFT_OP (root->right) &&
5667 IS_RIGHT_OP (root->left))
5670 if (!SPEC_USIGN (TETYPE (root->left->left)))
5673 if (!IS_AST_LIT_VALUE (root->left->right) ||
5674 !IS_AST_LIT_VALUE (root->right->right))
5677 /* make sure it is the same symbol */
5678 if (!isAstEqual (root->left->left,
5682 if (AST_ULONG_VALUE (root->left->right) != 1)
5685 if (AST_ULONG_VALUE (root->right->right) !=
5686 (getSize (TTYPE (root->left->left)) * 8 - 1))
5689 /* make sure the port supports RRC */
5690 if (port->hasExtBitOp
5691 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5694 /* whew got the first case : create the AST */
5695 return newNode (RRC, root->left->left, NULL);
5699 /* fourth and last case for now */
5700 /* (?symbol << 7) | (?symbol >> 1) */
5701 if (IS_RIGHT_OP (root->right) &&
5702 IS_LEFT_OP (root->left))
5705 if (!SPEC_USIGN (TETYPE (root->left->left)))
5708 if (!IS_AST_LIT_VALUE (root->left->right) ||
5709 !IS_AST_LIT_VALUE (root->right->right))
5712 /* make sure it is the same symbol */
5713 if (!isAstEqual (root->left->left,
5717 if (AST_ULONG_VALUE (root->right->right) != 1)
5720 if (AST_ULONG_VALUE (root->left->right) !=
5721 (getSize (TTYPE (root->left->left)) * 8 - 1))
5724 /* make sure the port supports RRC */
5725 if (port->hasExtBitOp
5726 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5729 /* whew got the first case : create the AST */
5730 return newNode (RRC, root->left->left, NULL);
5734 /* not found return root */
5738 /*-----------------------------------------------------------------*/
5739 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5740 /*-----------------------------------------------------------------*/
5742 optimizeSWAP (ast * root)
5744 /* will look for trees of the form
5745 (?expr << 4) | (?expr >> 4) or
5746 (?expr >> 4) | (?expr << 4) will make that
5747 into a SWAP : operation ..
5748 note : by 4 I mean (number of bits required to hold the
5750 /* if the root operation is not a | operation then not */
5751 if (!IS_BITOR (root))
5754 /* (?expr << 4) | (?expr >> 4) */
5755 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5756 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5759 if (!SPEC_USIGN (TETYPE (root->left->left)))
5762 if (!IS_AST_LIT_VALUE (root->left->right) ||
5763 !IS_AST_LIT_VALUE (root->right->right))
5766 /* make sure it is the same expression */
5767 if (!isAstEqual (root->left->left,
5771 if (AST_ULONG_VALUE (root->left->right) !=
5772 (getSize (TTYPE (root->left->left)) * 4))
5775 if (AST_ULONG_VALUE (root->right->right) !=
5776 (getSize (TTYPE (root->left->left)) * 4))
5779 /* make sure the port supports SWAP */
5780 if (port->hasExtBitOp
5781 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5784 /* found it : create the AST */
5785 return newNode (SWAP, root->left->left, NULL);
5789 /* not found return root */
5793 /*-----------------------------------------------------------------*/
5794 /* optimizeCompare - optimizes compares for bit variables */
5795 /*-----------------------------------------------------------------*/
5797 optimizeCompare (ast * root)
5799 ast *optExpr = NULL;
5802 unsigned int litValue;
5804 /* if nothing then return nothing */
5808 /* if not a compare op then do leaves */
5809 if (!IS_COMPARE_OP (root))
5811 root->left = optimizeCompare (root->left);
5812 root->right = optimizeCompare (root->right);
5816 /* if left & right are the same then depending
5817 of the operation do */
5818 if (isAstEqual (root->left, root->right))
5820 switch (root->opval.op)
5825 optExpr = newAst_VALUE (constCharVal (0));
5830 optExpr = newAst_VALUE (constCharVal (1));
5834 return decorateType (optExpr, RESULT_TYPE_NONE);
5837 vleft = (root->left->type == EX_VALUE ?
5838 root->left->opval.val : NULL);
5840 vright = (root->right->type == EX_VALUE ?
5841 root->right->opval.val : NULL);
5843 /* if left is a BITVAR in BITSPACE */
5844 /* and right is a LITERAL then */
5845 /* optimize else do nothing */
5846 if (vleft && vright &&
5847 IS_BITVAR (vleft->etype) &&
5848 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5849 IS_LITERAL (vright->etype))
5852 /* if right side > 1 then comparison may never succeed */
5853 if ((litValue = (int) ulFromVal (vright)) > 1)
5855 werror (W_BAD_COMPARE);
5861 switch (root->opval.op)
5863 case '>': /* bit value greater than 1 cannot be */
5864 werror (W_BAD_COMPARE);
5868 case '<': /* bit value < 1 means 0 */
5870 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5873 case LE_OP: /* bit value <= 1 means no check */
5874 optExpr = newAst_VALUE (vright);
5877 case GE_OP: /* bit value >= 1 means only check for = */
5879 optExpr = newAst_VALUE (vleft);
5884 { /* literal is zero */
5885 switch (root->opval.op)
5887 case '<': /* bit value < 0 cannot be */
5888 werror (W_BAD_COMPARE);
5892 case '>': /* bit value > 0 means 1 */
5894 optExpr = newAst_VALUE (vleft);
5897 case LE_OP: /* bit value <= 0 means no check */
5898 case GE_OP: /* bit value >= 0 means no check */
5899 werror (W_BAD_COMPARE);
5903 case EQ_OP: /* bit == 0 means ! of bit */
5904 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5908 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5909 } /* end-of-if of BITVAR */
5915 /*-----------------------------------------------------------------*/
5916 /* addSymToBlock : adds the symbol to the first block we find */
5917 /*-----------------------------------------------------------------*/
5919 addSymToBlock (symbol * sym, ast * tree)
5921 /* reached end of tree or a leaf */
5922 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5926 if (IS_AST_OP (tree) &&
5927 tree->opval.op == BLOCK)
5930 symbol *lsym = copySymbol (sym);
5932 lsym->next = AST_VALUES (tree, sym);
5933 AST_VALUES (tree, sym) = lsym;
5937 addSymToBlock (sym, tree->left);
5938 addSymToBlock (sym, tree->right);
5941 /*-----------------------------------------------------------------*/
5942 /* processRegParms - do processing for register parameters */
5943 /*-----------------------------------------------------------------*/
5945 processRegParms (value * args, ast * body)
5949 if (IS_REGPARM (args->etype))
5950 addSymToBlock (args->sym, body);
5955 /*-----------------------------------------------------------------*/
5956 /* resetParmKey - resets the operandkeys for the symbols */
5957 /*-----------------------------------------------------------------*/
5958 DEFSETFUNC (resetParmKey)
5971 /*------------------------------------------------------------------*/
5972 /* fixupInlineLabel - change a label in an inlined function so that */
5973 /* it is always unique no matter how many times */
5974 /* the function is inlined. */
5975 /*------------------------------------------------------------------*/
5977 fixupInlineLabel (symbol * sym)
5979 char name[SDCC_NAME_MAX + 1];
5981 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5982 strcpy (sym->name, name);
5986 /*------------------------------------------------------------------*/
5987 /* copyAstLoc - copy location information (file, line, block, etc.) */
5988 /* from one ast node to another */
5989 /*------------------------------------------------------------------*/
5991 copyAstLoc (ast * dest, ast * src)
5993 dest->filename = src->filename;
5994 dest->lineno = src->lineno;
5995 dest->level = src->level;
5996 dest->block = src->block;
5997 dest->seqPoint = src->seqPoint;
6002 /*-----------------------------------------------------------------*/
6003 /* fixupInline - perform various fixups on an inline function tree */
6004 /* to take into account that it is no longer a */
6005 /* stand-alone function. */
6006 /*-----------------------------------------------------------------*/
6008 fixupInline (ast * tree, int level)
6010 tree->block = currBlockno;
6012 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6019 /* Add any declared variables back into the symbol table */
6020 decls = tree->values.sym;
6023 decls->level = level;
6024 decls->block = currBlockno;
6025 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6026 decls = decls->next;
6030 tree->level = level;
6032 /* Update symbols */
6033 if (IS_AST_VALUE (tree) &&
6034 tree->opval.val->sym)
6036 symbol * sym = tree->opval.val->sym;
6039 sym->block = currBlockno;
6042 SYM_SPIL_LOC (sym) = NULL;
6045 /* If the symbol is a label, we need to renumber it */
6047 fixupInlineLabel (sym);
6050 /* Update IFX target labels */
6051 if (tree->type == EX_OP && tree->opval.op == IFX)
6053 if (tree->trueLabel)
6054 fixupInlineLabel (tree->trueLabel);
6055 if (tree->falseLabel)
6056 fixupInlineLabel (tree->falseLabel);
6059 /* Replace RETURN with optional assignment and a GOTO to the end */
6060 /* of the inlined function */
6061 if (tree->type == EX_OP && tree->opval.op == RETURN)
6063 ast * assignTree = NULL;
6066 if (inlineState.retsym && tree->right)
6068 assignTree = newNode ('=',
6069 newAst_VALUE (symbolVal (inlineState.retsym)),
6071 copyAstLoc (assignTree, tree);
6074 gotoTree = newNode (GOTO,
6075 newAst_VALUE (symbolVal (inlineState.retlab)),
6077 copyAstLoc (gotoTree, tree);
6079 tree->opval.op = NULLOP;
6080 tree->left = assignTree;
6081 tree->right = gotoTree;
6084 /* Update any children */
6086 fixupInline (tree->left, level);
6088 fixupInline (tree->right, level);
6090 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6092 symbol * label = tree->left->opval.val->sym;
6094 label->key = labelKey++;
6095 /* Add this label back into the symbol table */
6096 addSym (LabelTab, label, label->name, label->level, 0, 0);
6100 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6106 /*-----------------------------------------------------------------*/
6107 /* inlineAddDecl - add a variable declaration to an ast block. It */
6108 /* is also added to the symbol table if addSymTab */
6110 /*-----------------------------------------------------------------*/
6112 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6115 SYM_SPIL_LOC (sym) = NULL;
6119 symbol **decl = &(block->values.sym);
6121 sym->level = block->level;
6122 sym->block = block->block;
6126 if (strcmp ((*decl)->name, sym->name) == 0)
6128 decl = &( (*decl)->next );
6134 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6140 /*-----------------------------------------------------------------*/
6141 /* inlineTempVar - create a temporary variable for inlining */
6142 /*-----------------------------------------------------------------*/
6144 inlineTempVar (sym_link * type, int level)
6148 sym = newSymbol (genSymName(level), level );
6149 sym->type = copyLinkChain (type);
6150 sym->etype = getSpec(sym->type);
6151 SPEC_SCLS (sym->etype) = S_AUTO;
6152 SPEC_OCLS (sym->etype) = NULL;
6153 SPEC_EXTR (sym->etype) = 0;
6154 SPEC_STAT (sym->etype) = 0;
6155 if IS_SPEC (sym->type)
6156 SPEC_VOLATILE (sym->type) = 0;
6158 DCL_PTR_VOLATILE (sym->type) = 0;
6159 SPEC_ABSA (sym->etype) = 0;
6165 /*-----------------------------------------------------------------*/
6166 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6167 /*-----------------------------------------------------------------*/
6169 inlineFindParmRecurse (ast * parms, int *index)
6174 if (parms->type == EX_OP && parms->opval.op == PARAM)
6178 p=inlineFindParmRecurse (parms->left, index);
6181 p=inlineFindParmRecurse (parms->right, index);
6192 /*-----------------------------------------------------------------*/
6193 /* inlineFindParm - search an ast tree of parameters to find one */
6194 /* at a particular index (0=first parameter). */
6195 /* Returns NULL if not found. */
6196 /*-----------------------------------------------------------------*/
6198 inlineFindParm (ast * parms, int index)
6200 return inlineFindParmRecurse (parms, &index);
6203 /*-----------------------------------------------------------------*/
6204 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6205 /*-----------------------------------------------------------------*/
6207 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6214 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6215 if (tempBlockno > maxBlockno)
6216 maxBlockno = tempBlockno;
6218 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6219 if (tempBlockno > maxBlockno)
6220 maxBlockno = tempBlockno;
6222 if (tree->block > maxBlockno)
6223 maxBlockno = tree->block;
6230 /*-----------------------------------------------------------------*/
6231 /* expandInlineFuncs - replace calls to inline functions with the */
6232 /* function itself */
6233 /*-----------------------------------------------------------------*/
6235 expandInlineFuncs (ast * tree, ast * block)
6237 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6238 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6240 symbol * func = tree->left->opval.val->sym;
6243 /* The symbol is probably not bound yet, so find the real one */
6244 csym = findSymWithLevel (SymbolTab, func);
6248 /* Is this an inline function that we can inline? */
6249 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6251 symbol * retsym = NULL;
6259 /* Generate a label for the inlined function to branch to */
6260 /* in case it contains a return statement */
6261 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6264 inlineState.retlab = retlab;
6266 /* Build the subtree for the inlined function in the form: */
6267 /* { //inlinetree block */
6268 /* { //inlinetree2 block */
6269 /* inline_function_code; */
6273 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6274 copyAstLoc (temptree, tree);
6275 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6276 copyAstLoc (temptree, tree);
6277 temptree = newNode (BLOCK, NULL, temptree);
6278 copyAstLoc (temptree, tree);
6279 inlinetree2 = temptree;
6280 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6281 copyAstLoc (inlinetree, tree);
6283 /* To pass parameters to the inlined function, we need some */
6284 /* intermediate variables. This avoids scoping problems */
6285 /* when the parameter declaration names are used differently */
6286 /* during the function call. For example, a function */
6287 /* declared as func(int x, int y) but called as func(y,x). */
6288 /* { //inlinetree block */
6289 /* type1 temparg1 = argument1; */
6291 /* typen tempargn = argumentn; */
6292 /* { //inlinetree2 block */
6293 /* type1 param1 = temparg1; */
6295 /* typen paramn = tempargn; */
6296 /* inline_function_code; */
6300 args = FUNC_ARGS (func->type);
6307 ast * passedarg = inlineFindParm (tree->right, argIndex);
6311 werror(E_TOO_FEW_PARMS);
6315 temparg = inlineTempVar (args->sym->type, tree->level+1);
6316 inlineAddDecl (temparg, inlinetree, FALSE);
6318 assigntree = newNode ('=',
6319 newAst_VALUE (symbolVal (temparg)),
6321 assigntree->initMode=1; // tell that assignment is initializer
6322 inlinetree->right = newNode (NULLOP,
6326 parm = copySymbol (args->sym);
6327 inlineAddDecl (parm, inlinetree2, FALSE);
6330 assigntree = newNode ('=',
6331 newAst_VALUE (symbolVal (parm)),
6332 newAst_VALUE (symbolVal (temparg)));
6333 assigntree->initMode=1; // tell that assignment is initializer
6334 inlinetree2->right = newNode (NULLOP,
6336 inlinetree2->right);
6342 /* Handle the return type */
6343 if (!IS_VOID (func->type->next))
6345 /* Create a temporary symbol to hold the return value and */
6346 /* join it with the inlined function using the comma */
6347 /* operator. The fixupInline function will take care of */
6348 /* changing return statements into assignments to retsym. */
6349 /* (parameter passing and return label omitted for clarity) */
6350 /* rettype retsym; */
6352 /* {{inline_function_code}}, retsym */
6354 retsym = inlineTempVar (func->type->next, tree->level);
6355 inlineAddDecl (retsym, block, TRUE);
6357 tree->opval.op = ',';
6358 tree->left = inlinetree;
6359 tree->right = newAst_VALUE (symbolVal (retsym));
6363 tree->opval.op = NULLOP;
6365 tree->right = inlinetree;
6367 inlineState.retsym = retsym;
6369 /* Renumber the various internal counters on the inlined */
6370 /* function's tree nodes and symbols. Add the inlined */
6371 /* function's local variables to the appropriate scope(s). */
6372 /* Convert inlined return statements to an assignment to */
6373 /* retsym (if needed) and a goto retlab. */
6374 fixupInline (inlinetree, inlinetree->level);
6375 inlineState.count++;
6379 /* Recursively continue to search for functions to inline. */
6380 if (IS_AST_OP (tree))
6382 if (tree->opval.op == BLOCK)
6386 expandInlineFuncs (tree->left, block);
6388 expandInlineFuncs (tree->right, block);
6393 /*-----------------------------------------------------------------*/
6394 /* createFunction - This is the key node that calls the iCode for */
6395 /* generating the code for a function. Note code */
6396 /* is generated function by function, later when */
6397 /* add inter-procedural analysis this will change */
6398 /*-----------------------------------------------------------------*/
6400 createFunction (symbol * name, ast * body)
6406 iCode *piCode = NULL;
6409 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6410 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6412 /* if check function return 0 then some problem */
6413 if (checkFunction (name, NULL) == 0)
6416 /* create a dummy block if none exists */
6418 body = newNode (BLOCK, NULL, NULL);
6422 /* check if the function name already in the symbol table */
6423 if ((csym = findSym (SymbolTab, NULL, name->name)))
6426 /* special case for compiler defined functions
6427 we need to add the name to the publics list : this
6428 actually means we are now compiling the compiler
6432 addSet (&publics, name);
6437 addSymChain (&name);
6438 allocVariables (name);
6440 name->lastLine = lexLineno;
6443 /* set the stack pointer */
6444 stackPtr = -port->stack.direction * port->stack.call_overhead;
6447 if (IFFUNC_ISISR (name->type))
6448 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6450 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6452 if (options.useXstack)
6453 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6455 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6458 fetype = getSpec (name->type); /* get the specifier for the function */
6459 /* if this is a reentrant function then */
6460 if (IFFUNC_ISREENT (name->type))
6463 inlineState.count = 0;
6464 savedBlockno = currBlockno;
6465 currBlockno = inlineFindMaxBlockno (body, 0);
6466 expandInlineFuncs (body, NULL);
6467 currBlockno = savedBlockno;
6469 if (FUNC_ISINLINE (name->type))
6470 name->funcTree = copyAst (body);
6472 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6474 /* do processing for parameters that are passed in registers */
6475 processRegParms (FUNC_ARGS(name->type), body);
6477 /* set the stack pointer */
6481 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6483 /* allocate & autoinit the block variables */
6484 processBlockVars (body, &stack, ALLOCATE);
6486 /* name needs to be mangled */
6487 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6489 body = resolveSymbols (body); /* resolve the symbols */
6490 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6492 /* save the stack information */
6493 if (options.useXstack)
6494 name->xstack = SPEC_STAK (fetype) = stack;
6496 name->stack = SPEC_STAK (fetype) = stack;
6498 ex = newAst_VALUE (symbolVal (name)); /* create name */
6499 ex = newNode (FUNCTION, ex, body);
6500 ex->values.args = FUNC_ARGS(name->type);
6502 if (options.dump_tree)
6507 /* Do not generate code for inline functions unless extern also. */
6509 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6512 /* Temporary hack: always generate code for static inline functions. */
6513 /* Ideally static inline functions should only be generated if needed. */
6514 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6518 /* create the node & generate intermediate code */
6520 codeOutBuf = &code->oBuf;
6521 piCode = iCodeFromAst (ex);
6522 name->generated = 1;
6527 eBBlockFromiCode (piCode);
6529 /* if there are any statics then do them */
6532 GcurMemmap = statsg;
6533 codeOutBuf = &statsg->oBuf;
6534 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6540 /* dealloc the block variables */
6541 processBlockVars (body, &stack, DEALLOCATE);
6542 outputDebugStackSymbols();
6543 /* deallocate paramaters */
6544 deallocParms (FUNC_ARGS(name->type));
6546 if (IFFUNC_ISREENT (name->type))
6549 /* we are done freeup memory & cleanup */
6551 if (port->reset_labelKey) labelKey = 1;
6553 FUNC_HASBODY(name->type) = 1;
6554 addSet (&operKeyReset, name);
6555 applyToSet (operKeyReset, resetParmKey);
6560 cleanUpLevel (LabelTab, 0);
6561 cleanUpBlock (StructTab, 1);
6562 cleanUpBlock (TypedefTab, 1);
6564 xstack->syms = NULL;
6565 istack->syms = NULL;
6570 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6571 /*-----------------------------------------------------------------*/
6572 /* ast_print : prints the ast (for debugging purposes) */
6573 /*-----------------------------------------------------------------*/
6575 void ast_print (ast * tree, FILE *outfile, int indent)
6580 /* can print only decorated trees */
6581 if (!tree->decorated) return;
6583 /* if any child is an error | this one is an error do nothing */
6584 if (tree->isError ||
6585 (tree->left && tree->left->isError) ||
6586 (tree->right && tree->right->isError)) {
6587 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6591 /* print the line */
6592 /* if not block & function */
6593 if (tree->type == EX_OP &&
6594 (tree->opval.op != FUNCTION &&
6595 tree->opval.op != BLOCK &&
6596 tree->opval.op != NULLOP)) {
6599 if (tree->opval.op == FUNCTION) {
6601 value *args=FUNC_ARGS(tree->left->opval.val->type);
6602 fprintf(outfile,"FUNCTION (%s=%p) type (",
6603 tree->left->opval.val->name, tree);
6604 printTypeChain (tree->left->opval.val->type->next,outfile);
6605 fprintf(outfile,") args (");
6608 fprintf (outfile, ", ");
6610 printTypeChain (args ? args->type : NULL, outfile);
6612 args= args ? args->next : NULL;
6614 fprintf(outfile,")\n");
6615 ast_print(tree->left,outfile,indent);
6616 ast_print(tree->right,outfile,indent);
6619 if (tree->opval.op == BLOCK) {
6620 symbol *decls = tree->values.sym;
6621 INDENT(indent,outfile);
6622 fprintf(outfile,"{\n");
6624 INDENT(indent+2,outfile);
6625 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6626 decls->name, decls);
6627 printTypeChain(decls->type,outfile);
6628 fprintf(outfile,")\n");
6630 decls = decls->next;
6632 ast_print(tree->right,outfile,indent+2);
6633 INDENT(indent,outfile);
6634 fprintf(outfile,"}\n");
6637 if (tree->opval.op == NULLOP) {
6638 ast_print(tree->left,outfile,indent);
6639 ast_print(tree->right,outfile,indent);
6642 INDENT(indent,outfile);
6644 /*------------------------------------------------------------------*/
6645 /*----------------------------*/
6646 /* leaf has been reached */
6647 /*----------------------------*/
6648 /* if this is of type value */
6649 /* just get the type */
6650 if (tree->type == EX_VALUE) {
6652 if (IS_LITERAL (tree->opval.val->etype)) {
6653 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6654 if (SPEC_USIGN (tree->opval.val->etype))
6655 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6657 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6658 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6659 floatFromVal(tree->opval.val));
6660 } else if (tree->opval.val->sym) {
6661 /* if the undefined flag is set then give error message */
6662 if (tree->opval.val->sym->undefined) {
6663 fprintf(outfile,"UNDEFINED SYMBOL ");
6665 fprintf(outfile,"SYMBOL ");
6667 fprintf(outfile,"(%s=%p @ %p)",
6668 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6671 fprintf(outfile," type (");
6672 printTypeChain(tree->ftype,outfile);
6673 fprintf(outfile,")\n");
6675 fprintf(outfile,"\n");
6680 /* if type link for the case of cast */
6681 if (tree->type == EX_LINK) {
6682 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6683 printTypeChain(tree->opval.lnk,outfile);
6684 fprintf(outfile,")\n");
6689 /* depending on type of operator do */
6691 switch (tree->opval.op) {
6692 /*------------------------------------------------------------------*/
6693 /*----------------------------*/
6695 /*----------------------------*/
6697 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6698 printTypeChain(tree->ftype,outfile);
6699 fprintf(outfile,")\n");
6700 ast_print(tree->left,outfile,indent+2);
6701 ast_print(tree->right,outfile,indent+2);
6704 /*------------------------------------------------------------------*/
6705 /*----------------------------*/
6707 /*----------------------------*/
6709 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6710 printTypeChain(tree->ftype,outfile);
6711 fprintf(outfile,")\n");
6712 ast_print(tree->left,outfile,indent+2);
6713 ast_print(tree->right,outfile,indent+2);
6716 /*------------------------------------------------------------------*/
6717 /*----------------------------*/
6718 /* struct/union pointer */
6719 /*----------------------------*/
6721 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6722 printTypeChain(tree->ftype,outfile);
6723 fprintf(outfile,")\n");
6724 ast_print(tree->left,outfile,indent+2);
6725 ast_print(tree->right,outfile,indent+2);
6728 /*------------------------------------------------------------------*/
6729 /*----------------------------*/
6730 /* ++/-- operation */
6731 /*----------------------------*/
6734 fprintf(outfile,"post-");
6736 fprintf(outfile,"pre-");
6737 fprintf(outfile,"INC_OP (%p) type (",tree);
6738 printTypeChain(tree->ftype,outfile);
6739 fprintf(outfile,")\n");
6740 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6741 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6746 fprintf(outfile,"post-");
6748 fprintf(outfile,"pre-");
6749 fprintf(outfile,"DEC_OP (%p) type (",tree);
6750 printTypeChain(tree->ftype,outfile);
6751 fprintf(outfile,")\n");
6752 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6753 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6756 /*------------------------------------------------------------------*/
6757 /*----------------------------*/
6759 /*----------------------------*/
6762 fprintf(outfile,"& (%p) type (",tree);
6763 printTypeChain(tree->ftype,outfile);
6764 fprintf(outfile,")\n");
6765 ast_print(tree->left,outfile,indent+2);
6766 ast_print(tree->right,outfile,indent+2);
6768 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6769 printTypeChain(tree->ftype,outfile);
6770 fprintf(outfile,")\n");
6771 ast_print(tree->left,outfile,indent+2);
6772 ast_print(tree->right,outfile,indent+2);
6775 /*----------------------------*/
6777 /*----------------------------*/
6779 fprintf(outfile,"OR (%p) type (",tree);
6780 printTypeChain(tree->ftype,outfile);
6781 fprintf(outfile,")\n");
6782 ast_print(tree->left,outfile,indent+2);
6783 ast_print(tree->right,outfile,indent+2);
6785 /*------------------------------------------------------------------*/
6786 /*----------------------------*/
6788 /*----------------------------*/
6790 fprintf(outfile,"XOR (%p) type (",tree);
6791 printTypeChain(tree->ftype,outfile);
6792 fprintf(outfile,")\n");
6793 ast_print(tree->left,outfile,indent+2);
6794 ast_print(tree->right,outfile,indent+2);
6797 /*------------------------------------------------------------------*/
6798 /*----------------------------*/
6800 /*----------------------------*/
6802 fprintf(outfile,"DIV (%p) type (",tree);
6803 printTypeChain(tree->ftype,outfile);
6804 fprintf(outfile,")\n");
6805 ast_print(tree->left,outfile,indent+2);
6806 ast_print(tree->right,outfile,indent+2);
6808 /*------------------------------------------------------------------*/
6809 /*----------------------------*/
6811 /*----------------------------*/
6813 fprintf(outfile,"MOD (%p) type (",tree);
6814 printTypeChain(tree->ftype,outfile);
6815 fprintf(outfile,")\n");
6816 ast_print(tree->left,outfile,indent+2);
6817 ast_print(tree->right,outfile,indent+2);
6820 /*------------------------------------------------------------------*/
6821 /*----------------------------*/
6822 /* address dereference */
6823 /*----------------------------*/
6824 case '*': /* can be unary : if right is null then unary operation */
6826 fprintf(outfile,"DEREF (%p) type (",tree);
6827 printTypeChain(tree->ftype,outfile);
6828 fprintf(outfile,")\n");
6829 ast_print(tree->left,outfile,indent+2);
6832 /*------------------------------------------------------------------*/
6833 /*----------------------------*/
6834 /* multiplication */
6835 /*----------------------------*/
6836 fprintf(outfile,"MULT (%p) type (",tree);
6837 printTypeChain(tree->ftype,outfile);
6838 fprintf(outfile,")\n");
6839 ast_print(tree->left,outfile,indent+2);
6840 ast_print(tree->right,outfile,indent+2);
6844 /*------------------------------------------------------------------*/
6845 /*----------------------------*/
6846 /* unary '+' operator */
6847 /*----------------------------*/
6851 fprintf(outfile,"UPLUS (%p) type (",tree);
6852 printTypeChain(tree->ftype,outfile);
6853 fprintf(outfile,")\n");
6854 ast_print(tree->left,outfile,indent+2);
6856 /*------------------------------------------------------------------*/
6857 /*----------------------------*/
6859 /*----------------------------*/
6860 fprintf(outfile,"ADD (%p) type (",tree);
6861 printTypeChain(tree->ftype,outfile);
6862 fprintf(outfile,")\n");
6863 ast_print(tree->left,outfile,indent+2);
6864 ast_print(tree->right,outfile,indent+2);
6867 /*------------------------------------------------------------------*/
6868 /*----------------------------*/
6870 /*----------------------------*/
6871 case '-': /* can be unary */
6873 fprintf(outfile,"UMINUS (%p) type (",tree);
6874 printTypeChain(tree->ftype,outfile);
6875 fprintf(outfile,")\n");
6876 ast_print(tree->left,outfile,indent+2);
6878 /*------------------------------------------------------------------*/
6879 /*----------------------------*/
6881 /*----------------------------*/
6882 fprintf(outfile,"SUB (%p) type (",tree);
6883 printTypeChain(tree->ftype,outfile);
6884 fprintf(outfile,")\n");
6885 ast_print(tree->left,outfile,indent+2);
6886 ast_print(tree->right,outfile,indent+2);
6889 /*------------------------------------------------------------------*/
6890 /*----------------------------*/
6892 /*----------------------------*/
6894 fprintf(outfile,"COMPL (%p) type (",tree);
6895 printTypeChain(tree->ftype,outfile);
6896 fprintf(outfile,")\n");
6897 ast_print(tree->left,outfile,indent+2);
6899 /*------------------------------------------------------------------*/
6900 /*----------------------------*/
6902 /*----------------------------*/
6904 fprintf(outfile,"NOT (%p) type (",tree);
6905 printTypeChain(tree->ftype,outfile);
6906 fprintf(outfile,")\n");
6907 ast_print(tree->left,outfile,indent+2);
6909 /*------------------------------------------------------------------*/
6910 /*----------------------------*/
6912 /*----------------------------*/
6914 fprintf(outfile,"RRC (%p) type (",tree);
6915 printTypeChain(tree->ftype,outfile);
6916 fprintf(outfile,")\n");
6917 ast_print(tree->left,outfile,indent+2);
6921 fprintf(outfile,"RLC (%p) type (",tree);
6922 printTypeChain(tree->ftype,outfile);
6923 fprintf(outfile,")\n");
6924 ast_print(tree->left,outfile,indent+2);
6927 fprintf(outfile,"SWAP (%p) type (",tree);
6928 printTypeChain(tree->ftype,outfile);
6929 fprintf(outfile,")\n");
6930 ast_print(tree->left,outfile,indent+2);
6933 fprintf(outfile,"GETHBIT (%p) type (",tree);
6934 printTypeChain(tree->ftype,outfile);
6935 fprintf(outfile,")\n");
6936 ast_print(tree->left,outfile,indent+2);
6939 fprintf(outfile,"GETABIT (%p) type (",tree);
6940 printTypeChain(tree->ftype,outfile);
6941 fprintf(outfile,")\n");
6942 ast_print(tree->left,outfile,indent+2);
6943 ast_print(tree->right,outfile,indent+2);
6946 fprintf(outfile,"GETBYTE (%p) type (",tree);
6947 printTypeChain(tree->ftype,outfile);
6948 fprintf(outfile,")\n");
6949 ast_print(tree->left,outfile,indent+2);
6950 ast_print(tree->right,outfile,indent+2);
6953 fprintf(outfile,"GETWORD (%p) type (",tree);
6954 printTypeChain(tree->ftype,outfile);
6955 fprintf(outfile,")\n");
6956 ast_print(tree->left,outfile,indent+2);
6957 ast_print(tree->right,outfile,indent+2);
6960 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6961 printTypeChain(tree->ftype,outfile);
6962 fprintf(outfile,")\n");
6963 ast_print(tree->left,outfile,indent+2);
6964 ast_print(tree->right,outfile,indent+2);
6967 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6968 printTypeChain(tree->ftype,outfile);
6969 fprintf(outfile,")\n");
6970 ast_print(tree->left,outfile,indent+2);
6971 ast_print(tree->right,outfile,indent+2);
6973 /*------------------------------------------------------------------*/
6974 /*----------------------------*/
6976 /*----------------------------*/
6977 case CAST: /* change the type */
6978 fprintf(outfile,"CAST (%p) from type (",tree);
6979 printTypeChain(tree->right->ftype,outfile);
6980 fprintf(outfile,") to type (");
6981 printTypeChain(tree->ftype,outfile);
6982 fprintf(outfile,")\n");
6983 ast_print(tree->right,outfile,indent+2);
6987 fprintf(outfile,"ANDAND (%p) type (",tree);
6988 printTypeChain(tree->ftype,outfile);
6989 fprintf(outfile,")\n");
6990 ast_print(tree->left,outfile,indent+2);
6991 ast_print(tree->right,outfile,indent+2);
6994 fprintf(outfile,"OROR (%p) type (",tree);
6995 printTypeChain(tree->ftype,outfile);
6996 fprintf(outfile,")\n");
6997 ast_print(tree->left,outfile,indent+2);
6998 ast_print(tree->right,outfile,indent+2);
7001 /*------------------------------------------------------------------*/
7002 /*----------------------------*/
7003 /* comparison operators */
7004 /*----------------------------*/
7006 fprintf(outfile,"GT(>) (%p) type (",tree);
7007 printTypeChain(tree->ftype,outfile);
7008 fprintf(outfile,")\n");
7009 ast_print(tree->left,outfile,indent+2);
7010 ast_print(tree->right,outfile,indent+2);
7013 fprintf(outfile,"LT(<) (%p) type (",tree);
7014 printTypeChain(tree->ftype,outfile);
7015 fprintf(outfile,")\n");
7016 ast_print(tree->left,outfile,indent+2);
7017 ast_print(tree->right,outfile,indent+2);
7020 fprintf(outfile,"LE(<=) (%p) type (",tree);
7021 printTypeChain(tree->ftype,outfile);
7022 fprintf(outfile,")\n");
7023 ast_print(tree->left,outfile,indent+2);
7024 ast_print(tree->right,outfile,indent+2);
7027 fprintf(outfile,"GE(>=) (%p) type (",tree);
7028 printTypeChain(tree->ftype,outfile);
7029 fprintf(outfile,")\n");
7030 ast_print(tree->left,outfile,indent+2);
7031 ast_print(tree->right,outfile,indent+2);
7034 fprintf(outfile,"EQ(==) (%p) type (",tree);
7035 printTypeChain(tree->ftype,outfile);
7036 fprintf(outfile,")\n");
7037 ast_print(tree->left,outfile,indent+2);
7038 ast_print(tree->right,outfile,indent+2);
7041 fprintf(outfile,"NE(!=) (%p) type (",tree);
7042 printTypeChain(tree->ftype,outfile);
7043 fprintf(outfile,")\n");
7044 ast_print(tree->left,outfile,indent+2);
7045 ast_print(tree->right,outfile,indent+2);
7046 /*------------------------------------------------------------------*/
7047 /*----------------------------*/
7049 /*----------------------------*/
7050 case SIZEOF: /* evaluate wihout code generation */
7051 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7054 /*------------------------------------------------------------------*/
7055 /*----------------------------*/
7056 /* conditional operator '?' */
7057 /*----------------------------*/
7059 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7060 printTypeChain(tree->ftype,outfile);
7061 fprintf(outfile,")\n");
7062 ast_print(tree->left,outfile,indent+2);
7063 ast_print(tree->right,outfile,indent+2);
7067 fprintf(outfile,"COLON(:) (%p) type (",tree);
7068 printTypeChain(tree->ftype,outfile);
7069 fprintf(outfile,")\n");
7070 ast_print(tree->left,outfile,indent+2);
7071 ast_print(tree->right,outfile,indent+2);
7074 /*------------------------------------------------------------------*/
7075 /*----------------------------*/
7076 /* assignment operators */
7077 /*----------------------------*/
7079 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7080 printTypeChain(tree->ftype,outfile);
7081 fprintf(outfile,")\n");
7082 ast_print(tree->left,outfile,indent+2);
7083 ast_print(tree->right,outfile,indent+2);
7086 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7087 printTypeChain(tree->ftype,outfile);
7088 fprintf(outfile,")\n");
7089 ast_print(tree->left,outfile,indent+2);
7090 ast_print(tree->right,outfile,indent+2);
7093 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7094 printTypeChain(tree->ftype,outfile);
7095 fprintf(outfile,")\n");
7096 ast_print(tree->left,outfile,indent+2);
7097 ast_print(tree->right,outfile,indent+2);
7100 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7101 printTypeChain(tree->ftype,outfile);
7102 fprintf(outfile,")\n");
7103 ast_print(tree->left,outfile,indent+2);
7104 ast_print(tree->right,outfile,indent+2);
7107 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7108 printTypeChain(tree->ftype,outfile);
7109 fprintf(outfile,")\n");
7110 ast_print(tree->left,outfile,indent+2);
7111 ast_print(tree->right,outfile,indent+2);
7114 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7115 printTypeChain(tree->ftype,outfile);
7116 fprintf(outfile,")\n");
7117 ast_print(tree->left,outfile,indent+2);
7118 ast_print(tree->right,outfile,indent+2);
7121 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7122 printTypeChain(tree->ftype,outfile);
7123 fprintf(outfile,")\n");
7124 ast_print(tree->left,outfile,indent+2);
7125 ast_print(tree->right,outfile,indent+2);
7127 /*------------------------------------------------------------------*/
7128 /*----------------------------*/
7130 /*----------------------------*/
7132 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7133 printTypeChain(tree->ftype,outfile);
7134 fprintf(outfile,")\n");
7135 ast_print(tree->left,outfile,indent+2);
7136 ast_print(tree->right,outfile,indent+2);
7138 /*------------------------------------------------------------------*/
7139 /*----------------------------*/
7141 /*----------------------------*/
7143 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7144 printTypeChain(tree->ftype,outfile);
7145 fprintf(outfile,")\n");
7146 ast_print(tree->left,outfile,indent+2);
7147 ast_print(tree->right,outfile,indent+2);
7149 /*------------------------------------------------------------------*/
7150 /*----------------------------*/
7151 /* straight assignemnt */
7152 /*----------------------------*/
7154 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7155 printTypeChain(tree->ftype,outfile);
7156 fprintf(outfile,")\n");
7157 ast_print(tree->left,outfile,indent+2);
7158 ast_print(tree->right,outfile,indent+2);
7160 /*------------------------------------------------------------------*/
7161 /*----------------------------*/
7162 /* comma operator */
7163 /*----------------------------*/
7165 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7166 printTypeChain(tree->ftype,outfile);
7167 fprintf(outfile,")\n");
7168 ast_print(tree->left,outfile,indent+2);
7169 ast_print(tree->right,outfile,indent+2);
7171 /*------------------------------------------------------------------*/
7172 /*----------------------------*/
7174 /*----------------------------*/
7177 fprintf(outfile,"CALL (%p) type (",tree);
7178 printTypeChain(tree->ftype,outfile);
7179 fprintf(outfile,")\n");
7180 ast_print(tree->left,outfile,indent+2);
7181 ast_print(tree->right,outfile,indent+2);
7184 fprintf(outfile,"PARMS\n");
7185 ast_print(tree->left,outfile,indent+2);
7186 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7187 ast_print(tree->right,outfile,indent+2);
7190 /*------------------------------------------------------------------*/
7191 /*----------------------------*/
7192 /* return statement */
7193 /*----------------------------*/
7195 fprintf(outfile,"RETURN (%p) type (",tree);
7197 printTypeChain(tree->right->ftype,outfile);
7199 fprintf(outfile,")\n");
7200 ast_print(tree->right,outfile,indent+2);
7202 /*------------------------------------------------------------------*/
7203 /*----------------------------*/
7204 /* label statement */
7205 /*----------------------------*/
7207 fprintf(outfile,"LABEL (%p)\n",tree);
7208 ast_print(tree->left,outfile,indent+2);
7209 ast_print(tree->right,outfile,indent);
7211 /*------------------------------------------------------------------*/
7212 /*----------------------------*/
7213 /* switch statement */
7214 /*----------------------------*/
7218 fprintf(outfile,"SWITCH (%p) ",tree);
7219 ast_print(tree->left,outfile,0);
7220 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7221 INDENT(indent+2,outfile);
7222 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7223 (int) ulFromVal(val),
7224 tree->values.switchVals.swNum,
7225 (int) ulFromVal(val));
7227 ast_print(tree->right,outfile,indent);
7230 /*------------------------------------------------------------------*/
7231 /*----------------------------*/
7233 /*----------------------------*/
7235 fprintf(outfile,"IF (%p) \n",tree);
7236 ast_print(tree->left,outfile,indent+2);
7237 if (tree->trueLabel) {
7238 INDENT(indent+2,outfile);
7239 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7241 if (tree->falseLabel) {
7242 INDENT(indent+2,outfile);
7243 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7245 ast_print(tree->right,outfile,indent+2);
7247 /*----------------------------*/
7248 /* goto Statement */
7249 /*----------------------------*/
7251 fprintf(outfile,"GOTO (%p) \n",tree);
7252 ast_print(tree->left,outfile,indent+2);
7253 fprintf(outfile,"\n");
7255 /*------------------------------------------------------------------*/
7256 /*----------------------------*/
7258 /*----------------------------*/
7260 fprintf(outfile,"FOR (%p) \n",tree);
7261 if (AST_FOR( tree, initExpr)) {
7262 INDENT(indent+2,outfile);
7263 fprintf(outfile,"INIT EXPR ");
7264 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7266 if (AST_FOR( tree, condExpr)) {
7267 INDENT(indent+2,outfile);
7268 fprintf(outfile,"COND EXPR ");
7269 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7271 if (AST_FOR( tree, loopExpr)) {
7272 INDENT(indent+2,outfile);
7273 fprintf(outfile,"LOOP EXPR ");
7274 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7276 fprintf(outfile,"FOR LOOP BODY \n");
7277 ast_print(tree->left,outfile,indent+2);
7280 fprintf(outfile,"CRITICAL (%p) \n",tree);
7281 ast_print(tree->left,outfile,indent+2);
7289 ast_print(t,stdout,0);
7292 /*-----------------------------------------------------------------*/
7293 /* astErrors : returns non-zero if errors present in tree */
7294 /*-----------------------------------------------------------------*/
7295 int astErrors(ast *t)
7304 if (t->type == EX_VALUE
7305 && t->opval.val->sym
7306 && t->opval.val->sym->undefined)
7309 errors += astErrors(t->left);
7310 errors += astErrors(t->right);