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 rules */
1803 /* 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
1813 any arithmetic operation
1814 b) There are no function calls
1815 c) all jumps are within the body
1816 d) address of loop control variable not taken
1817 e) if an assignment has a pointer on the
1818 left hand side make sure right does not have
1819 loop control variable */
1821 /* if we reach the end or a leaf then true */
1822 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1825 /* if anything else is "volatile" */
1826 if (IS_VOLATILE (TETYPE (pbody)))
1829 /* we will walk the body in a pre-order traversal for
1831 switch (pbody->opval.op)
1833 /*------------------------------------------------------------------*/
1835 // if the loopvar is used as an index
1836 /* array op is commutative -- must check both left & right */
1837 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1840 return isConformingBody (pbody->right, sym, body)
1841 && isConformingBody (pbody->left, sym, body);
1843 /*------------------------------------------------------------------*/
1848 /*------------------------------------------------------------------*/
1852 /* sure we are not sym is not modified */
1854 IS_AST_SYM_VALUE (pbody->left) &&
1855 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1859 IS_AST_SYM_VALUE (pbody->right) &&
1860 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1865 /*------------------------------------------------------------------*/
1867 case '*': /* can be unary : if right is null then unary operation */
1872 /* if right is NULL then unary operation */
1873 /*------------------------------------------------------------------*/
1874 /*----------------------------*/
1876 /*----------------------------*/
1879 if (IS_AST_SYM_VALUE (pbody->left) &&
1880 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1883 return isConformingBody (pbody->left, sym, body);
1887 if (astHasSymbol (pbody->left, sym) ||
1888 astHasSymbol (pbody->right, sym))
1893 /*------------------------------------------------------------------*/
1904 if (IS_AST_SYM_VALUE (pbody->left) &&
1905 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1908 if (IS_AST_SYM_VALUE (pbody->right) &&
1909 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1912 return isConformingBody (pbody->left, sym, body) &&
1913 isConformingBody (pbody->right, sym, body);
1921 if (IS_AST_SYM_VALUE (pbody->left) &&
1922 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1924 return isConformingBody (pbody->left, sym, body);
1926 /*------------------------------------------------------------------*/
1938 case SIZEOF: /* evaluate wihout code generation */
1940 if (IS_AST_SYM_VALUE (pbody->left) &&
1941 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1944 if (IS_AST_SYM_VALUE (pbody->right) &&
1945 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1948 return isConformingBody (pbody->left, sym, body) &&
1949 isConformingBody (pbody->right, sym, body);
1951 /*------------------------------------------------------------------*/
1954 /* if left has a pointer & right has loop
1955 control variable then we cannot */
1956 if (astHasPointer (pbody->left) &&
1957 astHasSymbol (pbody->right, sym))
1959 if (astHasVolatile (pbody->left))
1962 if (IS_AST_SYM_VALUE (pbody->left)) {
1963 // if the loopvar has an assignment
1964 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1966 // if the loopvar is used in another (maybe conditional) block
1967 if (astHasSymbol (pbody->right, sym) &&
1968 (pbody->level >= body->level)) {
1973 if (astHasVolatile (pbody->left))
1976 if (astHasDeref(pbody->right)) return FALSE;
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 paramater then ok */
2006 if (sym->level && !astHasSymbol(pbody->right,sym))
2010 /*------------------------------------------------------------------*/
2011 /*----------------------------*/
2012 /* return statement */
2013 /*----------------------------*/
2018 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2023 if (astHasSymbol (pbody->left, sym))
2030 return isConformingBody (pbody->left, sym, body) &&
2031 isConformingBody (pbody->right, sym, body);
2037 /*-----------------------------------------------------------------*/
2038 /* isLoopReversible - takes a for loop as input && returns true */
2039 /* if the for loop is reversible. If yes will set the value of */
2040 /* the loop control var & init value & termination value */
2041 /*-----------------------------------------------------------------*/
2043 isLoopReversible (ast * loop, symbol ** loopCntrl,
2044 ast ** init, ast ** end)
2046 /* if option says don't do it then don't */
2047 if (optimize.noLoopReverse)
2049 /* there are several tests to determine this */
2051 /* for loop has to be of the form
2052 for ( <sym> = <const1> ;
2053 [<sym> < <const2>] ;
2054 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2056 if (!isLoopCountable (AST_FOR (loop, initExpr),
2057 AST_FOR (loop, condExpr),
2058 AST_FOR (loop, loopExpr),
2059 loopCntrl, init, end))
2062 /* now do some serious checking on the body of the loop
2065 return isConformingBody (loop->left, *loopCntrl, loop->left);
2069 /*-----------------------------------------------------------------*/
2070 /* replLoopSym - replace the loop sym by loop sym -1 */
2071 /*-----------------------------------------------------------------*/
2073 replLoopSym (ast * body, symbol * sym)
2076 if (!body || IS_AST_LINK (body))
2079 if (IS_AST_SYM_VALUE (body))
2082 if (isSymbolEqual (AST_SYMBOL (body), sym))
2086 body->opval.op = '-';
2087 body->left = newAst_VALUE (symbolVal (sym));
2088 body->right = newAst_VALUE (constCharVal (1));
2096 replLoopSym (body->left, sym);
2097 replLoopSym (body->right, sym);
2101 /*-----------------------------------------------------------------*/
2102 /* reverseLoop - do the actual loop reversal */
2103 /*-----------------------------------------------------------------*/
2105 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2109 /* create the following tree
2114 if (sym) goto for_continue ;
2117 /* put it together piece by piece */
2118 rloop = newNode (NULLOP,
2119 createIf (newAst_VALUE (symbolVal (sym)),
2121 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2124 newAst_VALUE (symbolVal (sym)),
2127 replLoopSym (loop->left, sym);
2128 setAstFileLine (rloop, init->filename, init->lineno);
2130 rloop = newNode (NULLOP,
2132 newAst_VALUE (symbolVal (sym)),
2133 newNode ('-', end, init)),
2134 createLabel (AST_FOR (loop, continueLabel),
2138 newNode (SUB_ASSIGN,
2139 newAst_VALUE (symbolVal (sym)),
2140 newAst_VALUE (constCharVal (1))),
2143 rloop->lineno=init->lineno;
2144 return decorateType (rloop, RESULT_TYPE_NONE);
2148 /*-----------------------------------------------------------------*/
2149 /* searchLitOp - search tree (*ops only) for an ast with literal */
2150 /*-----------------------------------------------------------------*/
2152 searchLitOp (ast *tree, ast **parent, const char *ops)
2156 if (tree && optimize.global_cse)
2158 /* is there a literal operand? */
2160 IS_AST_OP(tree->right) &&
2161 tree->right->right &&
2162 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2164 if (IS_LITERAL (RTYPE (tree->right)) !=
2165 IS_LITERAL (LTYPE (tree->right)))
2167 tree->right->decorated = 0;
2168 tree->decorated = 0;
2172 ret = searchLitOp (tree->right, parent, ops);
2177 IS_AST_OP(tree->left) &&
2178 tree->left->right &&
2179 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2181 if (IS_LITERAL (RTYPE (tree->left)) !=
2182 IS_LITERAL (LTYPE (tree->left)))
2184 tree->left->decorated = 0;
2185 tree->decorated = 0;
2189 ret = searchLitOp (tree->left, parent, ops);
2197 /*-----------------------------------------------------------------*/
2198 /* getResultFromType */
2199 /*-----------------------------------------------------------------*/
2201 getResultTypeFromType (sym_link *type)
2203 /* type = getSpec (type); */
2205 return RESULT_TYPE_BIT;
2206 if (IS_BITFIELD (type))
2208 int blen = SPEC_BLEN (type);
2211 return RESULT_TYPE_BIT;
2213 return RESULT_TYPE_CHAR;
2214 return RESULT_TYPE_INT;
2217 return RESULT_TYPE_CHAR;
2218 if (IS_INT (type) && !IS_LONG (type))
2219 return RESULT_TYPE_INT;
2220 return RESULT_TYPE_OTHER;
2223 /*-----------------------------------------------------------------*/
2224 /* addCast - adds casts to a type specified by RESULT_TYPE */
2225 /*-----------------------------------------------------------------*/
2227 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2230 bool upCasted = FALSE;
2234 case RESULT_TYPE_NONE:
2235 /* if thing smaller than int must be promoted to int */
2237 getSize (tree->etype) >= INTSIZE)
2238 /* promotion not necessary or already an int */
2240 /* char and bits: promote to int */
2241 newLink = newIntLink();
2244 case RESULT_TYPE_BIT:
2246 /* already an int */
2247 bitsForType (tree->etype) >= 16 ||
2248 /* bit to bit operation: don't promote, the code generators
2249 hopefully know everything about promotion rules */
2250 bitsForType (tree->etype) == 1)
2252 newLink = newIntLink();
2255 case RESULT_TYPE_CHAR:
2256 if (IS_CHAR (tree->etype) ||
2257 IS_FLOAT(tree->etype) ||
2258 IS_FIXED(tree->etype))
2260 newLink = newCharLink();
2262 case RESULT_TYPE_INT:
2264 if (getSize (tree->etype) > INTSIZE)
2266 /* warn ("Loosing significant digits"); */
2270 /* char: promote to int */
2272 getSize (tree->etype) >= INTSIZE)
2274 newLink = newIntLink();
2277 case RESULT_TYPE_IFX:
2278 case RESULT_TYPE_OTHER:
2280 /* return type is ifx, long, float: promote char to int */
2281 getSize (tree->etype) >= INTSIZE)
2283 newLink = newIntLink();
2289 tree->decorated = 0;
2290 tree = newNode (CAST, newAst_LINK (newLink), tree);
2291 tree->filename = tree->right->filename;
2292 tree->lineno = tree->right->lineno;
2293 /* keep unsigned type during cast to smaller type,
2294 but not when promoting from char to int */
2296 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2297 return decorateType (tree, resultType);
2300 /*-----------------------------------------------------------------*/
2301 /* resultTypePropagate - decides if resultType can be propagated */
2302 /*-----------------------------------------------------------------*/
2304 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2306 switch (tree->opval.op)
2323 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2324 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2325 return RESULT_TYPE_NONE;
2330 return RESULT_TYPE_NONE;
2334 return RESULT_TYPE_IFX;
2336 return RESULT_TYPE_NONE;
2340 /*-----------------------------------------------------------------*/
2341 /* getLeftResultType - gets type from left branch for propagation */
2342 /*-----------------------------------------------------------------*/
2344 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2346 switch (tree->opval.op)
2350 if (IS_PTR (LTYPE (tree)))
2351 return RESULT_TYPE_NONE;
2353 return getResultTypeFromType (LETYPE (tree));
2355 if (IS_PTR (currFunc->type->next))
2356 return RESULT_TYPE_NONE;
2358 return getResultTypeFromType (currFunc->type->next);
2360 if (!IS_ARRAY (LTYPE (tree)))
2362 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2363 return RESULT_TYPE_CHAR;
2370 /*------------------------------------------------------------------*/
2371 /* gatherImplicitVariables: assigns correct type information to */
2372 /* symbols and values created by replaceAstWithTemporary */
2373 /* and adds the symbols to the declarations list of the */
2374 /* innermost block that contains them */
2375 /*------------------------------------------------------------------*/
2377 gatherImplicitVariables (ast * tree, ast * block)
2382 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2384 /* keep track of containing scope */
2387 if (tree->type == EX_OP && tree->opval.op == '=' &&
2388 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2390 symbol *assignee = tree->left->opval.val->sym;
2392 /* special case for assignment to compiler-generated temporary variable:
2393 compute type of RHS, and set the symbol's type to match */
2394 if (assignee->type == NULL && assignee->infertype) {
2395 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2397 if (dtr != tree->right)
2400 assignee->type = copyLinkChain(TTYPE(dtr));
2401 assignee->etype = getSpec(assignee->type);
2402 SPEC_SCLS (assignee->etype) = S_AUTO;
2403 SPEC_OCLS (assignee->etype) = NULL;
2404 SPEC_EXTR (assignee->etype) = 0;
2405 SPEC_STAT (assignee->etype) = 0;
2406 SPEC_VOLATILE (assignee->etype) = 0;
2407 SPEC_ABSA (assignee->etype) = 0;
2409 wassertl(block != NULL, "implicit variable not contained in block");
2410 wassert(assignee->next == NULL);
2411 if (block != NULL) {
2412 symbol **decl = &(block->values.sym);
2415 wassert(*decl != assignee); /* should not already be in list */
2416 decl = &( (*decl)->next );
2423 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2424 tree->opval.val->type == NULL &&
2425 tree->opval.val->sym &&
2426 tree->opval.val->sym->infertype)
2428 /* fixup type of value for compiler-inferred temporary var */
2429 tree->opval.val->type = tree->opval.val->sym->type;
2430 tree->opval.val->etype = tree->opval.val->sym->etype;
2433 gatherImplicitVariables(tree->left, block);
2434 gatherImplicitVariables(tree->right, block);
2437 /*--------------------------------------------------------------------*/
2438 /* decorateType - compute type for this tree, also does type checking.*/
2439 /* This is done bottom up, since type has to flow upwards. */
2440 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2441 /* result is a char and the operand(s) are int's. */
2442 /* It also does constant folding, and parameter checking. */
2443 /*--------------------------------------------------------------------*/
2445 decorateType (ast * tree, RESULT_TYPE resultType)
2449 RESULT_TYPE resultTypeProp;
2454 /* if already has type then do nothing */
2455 if (tree->decorated)
2458 tree->decorated = 1;
2461 /* print the line */
2462 /* if not block & function */
2463 if (tree->type == EX_OP &&
2464 (tree->opval.op != FUNCTION &&
2465 tree->opval.op != BLOCK &&
2466 tree->opval.op != NULLOP))
2468 filename = tree->filename;
2469 lineno = tree->lineno;
2473 /* if any child is an error | this one is an error do nothing */
2474 if (tree->isError ||
2475 (tree->left && tree->left->isError) ||
2476 (tree->right && tree->right->isError))
2479 /*------------------------------------------------------------------*/
2480 /*----------------------------*/
2481 /* leaf has been reached */
2482 /*----------------------------*/
2483 filename = tree->filename;
2484 lineno = tree->lineno;
2485 /* if this is of type value */
2486 /* just get the type */
2487 if (tree->type == EX_VALUE)
2490 if (IS_LITERAL (tree->opval.val->etype))
2493 /* if this is a character array then declare it */
2494 if (IS_ARRAY (tree->opval.val->type))
2495 tree->opval.val = stringToSymbol (tree->opval.val);
2497 /* otherwise just copy the type information */
2498 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2502 if (tree->opval.val->sym)
2504 /* if the undefined flag is set then give error message */
2505 if (tree->opval.val->sym->undefined)
2507 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2509 TTYPE (tree) = TETYPE (tree) =
2510 tree->opval.val->type = tree->opval.val->sym->type =
2511 tree->opval.val->etype = tree->opval.val->sym->etype =
2512 copyLinkChain (INTTYPE);
2514 else if (tree->opval.val->sym->implicit)
2516 /* if implicit i.e. struct/union member then no type */
2517 TTYPE (tree) = TETYPE (tree) = NULL;
2521 /* copy the type from the value into the ast */
2522 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2524 /* and mark the symbol as referenced */
2525 tree->opval.val->sym->isref = 1;
2529 wassert(0); /* unreached: all values are literals or symbols */
2534 /* if type link for the case of cast */
2535 if (tree->type == EX_LINK)
2537 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2545 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2547 if (tree->left && tree->left->type == EX_OPERAND
2548 && (tree->left->opval.op == INC_OP
2549 || tree->left->opval.op == DEC_OP)
2550 && tree->left->left)
2552 tree->left->right = tree->left->left;
2553 tree->left->left = NULL;
2555 if (tree->right && tree->right->type == EX_OPERAND
2556 && (tree->right->opval.op == INC_OP
2557 || tree->right->opval.op == DEC_OP)
2558 && tree->right->left)
2560 tree->right->right = tree->right->left;
2561 tree->right->left = NULL;
2566 /* Before decorating the left branch we've to decide in dependence
2567 upon tree->opval.op, if resultType can be propagated */
2568 resultTypeProp = resultTypePropagate (tree, resultType);
2570 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2571 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2573 dtl = decorateType (tree->left, resultTypeProp);
2575 /* if an array node, we may need to swap branches */
2576 if (tree->opval.op == '[')
2578 /* determine which is the array & which the index */
2579 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2580 IS_INTEGRAL (LTYPE (tree)))
2582 ast *tempTree = tree->left;
2583 tree->left = tree->right;
2584 tree->right = tempTree;
2588 /* After decorating the left branch there's type information available
2589 in tree->left->?type. If the op is e.g. '=' we extract the type
2590 information from there and propagate it to the right branch. */
2591 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2593 switch (tree->opval.op)
2596 /* delay right side for '?' operator since conditional macro
2597 expansions might rely on this */
2601 /* decorate right side for CALL (parameter list) in processParms();
2602 there is resultType available */
2606 /* don't allocate string if it is a sizeof argument */
2608 dtr = decorateType (tree->right, resultTypeProp);
2612 dtr = decorateType (tree->right, resultTypeProp);
2616 /* this is to take care of situations
2617 when the tree gets rewritten */
2618 if (dtl != tree->left)
2620 if (dtr != tree->right)
2622 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2626 /* depending on type of operator do */
2628 switch (tree->opval.op)
2630 /*------------------------------------------------------------------*/
2631 /*----------------------------*/
2633 /*----------------------------*/
2636 /* first check if this is a array or a pointer */
2637 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2639 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2640 goto errorTreeReturn;
2643 /* check if the type of the idx */
2644 if (!IS_INTEGRAL (RTYPE (tree)))
2646 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2647 goto errorTreeReturn;
2650 /* if the left is an rvalue then error */
2653 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2654 goto errorTreeReturn;
2657 if (IS_LITERAL (RTYPE (tree)))
2659 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2660 int arraySize = DCL_ELEM (LTYPE (tree));
2661 if (arraySize && arrayIndex >= arraySize)
2663 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2668 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2669 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2672 /*------------------------------------------------------------------*/
2673 /*----------------------------*/
2675 /*----------------------------*/
2677 /* if this is not a structure */
2678 if (!IS_STRUCT (LTYPE (tree)))
2680 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2681 goto errorTreeReturn;
2683 TTYPE (tree) = structElemType (LTYPE (tree),
2684 (tree->right->type == EX_VALUE ?
2685 tree->right->opval.val : NULL));
2686 TETYPE (tree) = getSpec (TTYPE (tree));
2689 /*------------------------------------------------------------------*/
2690 /*----------------------------*/
2691 /* struct/union pointer */
2692 /*----------------------------*/
2694 /* if not pointer to a structure */
2695 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2697 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2698 goto errorTreeReturn;
2701 if (!IS_STRUCT (LTYPE (tree)->next))
2703 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2704 goto errorTreeReturn;
2707 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2708 (tree->right->type == EX_VALUE ?
2709 tree->right->opval.val : NULL));
2710 TETYPE (tree) = getSpec (TTYPE (tree));
2712 /* adjust the storage class */
2713 switch (DCL_TYPE(tree->left->ftype)) {
2715 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2718 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2721 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2724 SPEC_SCLS (TETYPE (tree)) = 0;
2727 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2730 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2733 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2736 SPEC_SCLS (TETYPE (tree)) = 0;
2743 /* This breaks with extern declarations, bitfields, and perhaps other */
2744 /* cases (gcse). Let's leave this optimization disabled for now and */
2745 /* ponder if there's a safe way to do this. -- EEP */
2747 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2748 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2750 /* If defined struct type at addr var
2751 then rewrite (&struct var)->member
2753 and define membertype at (addr+offsetof(struct var,member)) temp
2756 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2757 AST_SYMBOL(tree->right));
2759 sym = newSymbol(genSymName (0), 0);
2760 sym->type = TTYPE (tree);
2761 sym->etype = getSpec(sym->type);
2762 sym->lineDef = tree->lineno;
2765 SPEC_STAT (sym->etype) = 1;
2766 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2768 SPEC_ABSA(sym->etype) = 1;
2769 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2772 AST_VALUE (tree) = symbolVal(sym);
2775 tree->type = EX_VALUE;
2783 /*------------------------------------------------------------------*/
2784 /*----------------------------*/
2785 /* ++/-- operation */
2786 /*----------------------------*/
2790 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2791 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2792 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2793 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2802 /*------------------------------------------------------------------*/
2803 /*----------------------------*/
2805 /*----------------------------*/
2806 case '&': /* can be unary */
2807 /* if right is NULL then unary operation */
2808 if (tree->right) /* not an unary operation */
2811 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2813 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2814 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2815 printTypeChain (LTYPE (tree), stderr);
2816 fprintf (stderr, ",");
2817 printTypeChain (RTYPE (tree), stderr);
2818 fprintf (stderr, "\n");
2819 goto errorTreeReturn;
2822 /* if they are both literal */
2823 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2825 tree->type = EX_VALUE;
2826 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2827 valFromType (RETYPE (tree)), '&');
2829 tree->right = tree->left = NULL;
2830 TETYPE (tree) = tree->opval.val->etype;
2831 TTYPE (tree) = tree->opval.val->type;
2835 /* see if this is a GETHBIT operation if yes
2838 ast *otree = optimizeGetHbit (tree, resultType);
2841 return decorateType (otree, RESULT_TYPE_NONE);
2844 /* see if this is a GETABIT operation if yes
2847 ast *otree = optimizeGetAbit (tree, resultType);
2850 return decorateType (otree, RESULT_TYPE_NONE);
2853 /* see if this is a GETBYTE operation if yes
2856 ast *otree = optimizeGetByte (tree, resultType);
2859 return decorateType (otree, RESULT_TYPE_NONE);
2862 /* see if this is a GETWORD operation if yes
2865 ast *otree = optimizeGetWord (tree, resultType);
2868 return decorateType (otree, RESULT_TYPE_NONE);
2871 /* if left is a literal exchange left & right */
2872 if (IS_LITERAL (LTYPE (tree)))
2874 ast *tTree = tree->left;
2875 tree->left = tree->right;
2876 tree->right = tTree;
2879 /* if right is a literal and */
2880 /* we can find a 2nd literal in an and-tree then */
2881 /* rearrange the tree */
2882 if (IS_LITERAL (RTYPE (tree)))
2885 ast *litTree = searchLitOp (tree, &parent, "&");
2889 ast *tTree = litTree->left;
2890 litTree->left = tree->right;
2891 tree->right = tTree;
2892 /* both operands in litTree are literal now */
2893 decorateType (parent, resultType);
2897 LRVAL (tree) = RRVAL (tree) = 1;
2899 TTYPE (tree) = computeType (LTYPE (tree),
2903 TETYPE (tree) = getSpec (TTYPE (tree));
2908 /*------------------------------------------------------------------*/
2909 /*----------------------------*/
2911 /*----------------------------*/
2912 p = newLink (DECLARATOR);
2913 /* if bit field then error */
2914 if (IS_BITVAR (tree->left->etype))
2916 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2917 goto errorTreeReturn;
2920 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2922 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2923 goto errorTreeReturn;
2926 if (IS_FUNC (LTYPE (tree)))
2928 // this ought to be ignored
2929 return (tree->left);
2932 if (IS_LITERAL(LTYPE(tree)))
2934 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2935 goto errorTreeReturn;
2940 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2941 goto errorTreeReturn;
2944 DCL_TYPE (p) = POINTER;
2945 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2946 DCL_TYPE (p) = CPOINTER;
2947 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2948 DCL_TYPE (p) = FPOINTER;
2949 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2950 DCL_TYPE (p) = PPOINTER;
2951 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2952 DCL_TYPE (p) = IPOINTER;
2953 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2954 DCL_TYPE (p) = EEPPOINTER;
2955 else if (SPEC_OCLS(tree->left->etype))
2956 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2958 DCL_TYPE (p) = POINTER;
2960 if (IS_AST_SYM_VALUE (tree->left))
2962 AST_SYMBOL (tree->left)->addrtaken = 1;
2963 AST_SYMBOL (tree->left)->allocreq = 1;
2966 p->next = LTYPE (tree);
2968 TETYPE (tree) = getSpec (TTYPE (tree));
2973 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2974 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2976 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2977 AST_SYMBOL(tree->left->right));
2978 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2979 valueFromLit(element->offset));
2982 tree->type = EX_VALUE;
2983 tree->values.literalFromCast = 1;
2989 /*------------------------------------------------------------------*/
2990 /*----------------------------*/
2992 /*----------------------------*/
2994 /* if the rewrite succeeds then don't go any further */
2996 ast *wtree = optimizeRRCRLC (tree);
2998 return decorateType (wtree, RESULT_TYPE_NONE);
3000 wtree = optimizeSWAP (tree);
3002 return decorateType (wtree, RESULT_TYPE_NONE);
3005 /* if left is a literal exchange left & right */
3006 if (IS_LITERAL (LTYPE (tree)))
3008 ast *tTree = tree->left;
3009 tree->left = tree->right;
3010 tree->right = tTree;
3013 /* if right is a literal and */
3014 /* we can find a 2nd literal in an or-tree then */
3015 /* rearrange the tree */
3016 if (IS_LITERAL (RTYPE (tree)))
3019 ast *litTree = searchLitOp (tree, &parent, "|");
3023 ast *tTree = litTree->left;
3024 litTree->left = tree->right;
3025 tree->right = tTree;
3026 /* both operands in tTree are literal now */
3027 decorateType (parent, resultType);
3032 /*------------------------------------------------------------------*/
3033 /*----------------------------*/
3035 /*----------------------------*/
3037 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3039 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3040 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3041 printTypeChain (LTYPE (tree), stderr);
3042 fprintf (stderr, ",");
3043 printTypeChain (RTYPE (tree), stderr);
3044 fprintf (stderr, "\n");
3045 goto errorTreeReturn;
3048 /* if they are both literal then rewrite the tree */
3049 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3051 tree->type = EX_VALUE;
3052 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3053 valFromType (RETYPE (tree)),
3055 tree->right = tree->left = NULL;
3056 TETYPE (tree) = tree->opval.val->etype;
3057 TTYPE (tree) = tree->opval.val->type;
3061 /* if left is a literal exchange left & right */
3062 if (IS_LITERAL (LTYPE (tree)))
3064 ast *tTree = tree->left;
3065 tree->left = tree->right;
3066 tree->right = tTree;
3069 /* if right is a literal and */
3070 /* we can find a 2nd literal in a xor-tree then */
3071 /* rearrange the tree */
3072 if (IS_LITERAL (RTYPE (tree)) &&
3073 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3076 ast *litTree = searchLitOp (tree, &parent, "^");
3080 ast *tTree = litTree->left;
3081 litTree->left = tree->right;
3082 tree->right = tTree;
3083 /* both operands in litTree are literal now */
3084 decorateType (parent, resultType);
3088 LRVAL (tree) = RRVAL (tree) = 1;
3090 TTYPE (tree) = computeType (LTYPE (tree),
3094 TETYPE (tree) = getSpec (TTYPE (tree));
3098 /*------------------------------------------------------------------*/
3099 /*----------------------------*/
3101 /*----------------------------*/
3103 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3105 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3106 goto errorTreeReturn;
3108 /* if they are both literal then */
3109 /* rewrite the tree */
3110 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3112 tree->type = EX_VALUE;
3113 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3114 valFromType (RETYPE (tree)));
3115 tree->right = tree->left = NULL;
3116 TETYPE (tree) = getSpec (TTYPE (tree) =
3117 tree->opval.val->type);
3121 LRVAL (tree) = RRVAL (tree) = 1;
3123 TETYPE (tree) = getSpec (TTYPE (tree) =
3124 computeType (LTYPE (tree),
3129 /* if right is a literal and */
3130 /* left is also a division by a literal then */
3131 /* rearrange the tree */
3132 if (IS_LITERAL (RTYPE (tree))
3133 /* avoid infinite loop */
3134 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3137 ast *litTree = searchLitOp (tree, &parent, "/");
3140 if (IS_LITERAL (RTYPE (litTree)))
3144 litTree->right = newNode ('*',
3146 copyAst (tree->right));
3147 litTree->right->filename = tree->filename;
3148 litTree->right->lineno = tree->lineno;
3150 tree->right->opval.val = constCharVal (1);
3151 decorateType (parent, resultType);
3155 /* litTree->left is literal: no gcse possible.
3156 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3157 this would cause an infinit loop. */
3158 parent->decorated = 1;
3159 decorateType (litTree, resultType);
3166 /*------------------------------------------------------------------*/
3167 /*----------------------------*/
3169 /*----------------------------*/
3171 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3173 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3174 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3175 printTypeChain (LTYPE (tree), stderr);
3176 fprintf (stderr, ",");
3177 printTypeChain (RTYPE (tree), stderr);
3178 fprintf (stderr, "\n");
3179 goto errorTreeReturn;
3181 /* if they are both literal then */
3182 /* rewrite the tree */
3183 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3185 tree->type = EX_VALUE;
3186 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3187 valFromType (RETYPE (tree)));
3188 tree->right = tree->left = NULL;
3189 TETYPE (tree) = getSpec (TTYPE (tree) =
3190 tree->opval.val->type);
3193 LRVAL (tree) = RRVAL (tree) = 1;
3194 TETYPE (tree) = getSpec (TTYPE (tree) =
3195 computeType (LTYPE (tree),
3201 /*------------------------------------------------------------------*/
3202 /*----------------------------*/
3203 /* address dereference */
3204 /*----------------------------*/
3205 case '*': /* can be unary : if right is null then unary operation */
3208 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3210 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3211 goto errorTreeReturn;
3216 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3217 goto errorTreeReturn;
3219 if (IS_ADDRESS_OF_OP(tree->left))
3221 /* replace *&obj with obj */
3222 return tree->left->left;
3224 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3225 TETYPE (tree) = getSpec (TTYPE (tree));
3226 /* adjust the storage class */
3227 switch (DCL_TYPE(tree->left->ftype)) {
3229 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3232 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3235 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3238 SPEC_SCLS (TETYPE (tree)) = 0;
3241 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3244 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3247 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3250 SPEC_SCLS (TETYPE (tree)) = 0;
3259 /*------------------------------------------------------------------*/
3260 /*----------------------------*/
3261 /* multiplication */
3262 /*----------------------------*/
3263 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3265 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3266 goto errorTreeReturn;
3269 /* if they are both literal then */
3270 /* rewrite the tree */
3271 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3273 tree->type = EX_VALUE;
3274 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3275 valFromType (RETYPE (tree)));
3276 tree->right = tree->left = NULL;
3277 TETYPE (tree) = getSpec (TTYPE (tree) =
3278 tree->opval.val->type);
3282 /* if left is a literal exchange left & right */
3283 if (IS_LITERAL (LTYPE (tree)))
3285 ast *tTree = tree->left;
3286 tree->left = tree->right;
3287 tree->right = tTree;
3290 /* if right is a literal and */
3291 /* we can find a 2nd literal in a mul-tree then */
3292 /* rearrange the tree */
3293 if (IS_LITERAL (RTYPE (tree)))
3296 ast *litTree = searchLitOp (tree, &parent, "*");
3300 ast *tTree = litTree->left;
3301 litTree->left = tree->right;
3302 tree->right = tTree;
3303 /* both operands in litTree are literal now */
3304 decorateType (parent, resultType);
3308 LRVAL (tree) = RRVAL (tree) = 1;
3309 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3310 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3311 TETYPE (tree) = getSpec (TTYPE (tree) =
3312 computeType (LTYPE (tree),
3319 /*------------------------------------------------------------------*/
3320 /*----------------------------*/
3321 /* unary '+' operator */
3322 /*----------------------------*/
3327 if (!IS_ARITHMETIC (LTYPE (tree)))
3329 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3330 goto errorTreeReturn;
3333 /* if left is a literal then do it */
3334 if (IS_LITERAL (LTYPE (tree)))
3336 tree->type = EX_VALUE;
3337 tree->opval.val = valFromType (LETYPE (tree));
3339 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3343 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3347 /*------------------------------------------------------------------*/
3348 /*----------------------------*/
3350 /*----------------------------*/
3352 /* this is not a unary operation */
3353 /* if both pointers then problem */
3354 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3355 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3357 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3358 goto errorTreeReturn;
3361 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3362 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3364 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3365 goto errorTreeReturn;
3368 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3369 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3371 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3372 goto errorTreeReturn;
3374 /* if they are both literal then */
3375 /* rewrite the tree */
3376 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3378 tree->type = EX_VALUE;
3379 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3380 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3381 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3382 valFromType (RETYPE (tree)));
3383 tree->right = tree->left = NULL;
3384 TETYPE (tree) = getSpec (TTYPE (tree) =
3385 tree->opval.val->type);
3389 /* if the right is a pointer or left is a literal
3390 xchange left & right */
3391 if (IS_ARRAY (RTYPE (tree)) ||
3392 IS_PTR (RTYPE (tree)) ||
3393 IS_LITERAL (LTYPE (tree)))
3395 ast *tTree = tree->left;
3396 tree->left = tree->right;
3397 tree->right = tTree;
3400 /* if right is a literal and */
3401 /* left is also an addition/subtraction with a literal then */
3402 /* rearrange the tree */
3403 if (IS_LITERAL (RTYPE (tree)))
3405 ast *litTree, *parent;
3406 litTree = searchLitOp (tree, &parent, "+-");
3409 if (litTree->opval.op == '+')
3413 ast *tTree = litTree->left;
3414 litTree->left = tree->right;
3415 tree->right = tree->left;
3418 else if (litTree->opval.op == '-')
3420 if (IS_LITERAL (RTYPE (litTree)))
3424 ast *tTree = litTree->left;
3425 litTree->left = tree->right;
3426 tree->right = tTree;
3432 ast *tTree = litTree->right;
3433 litTree->right = tree->right;
3434 tree->right = tTree;
3435 litTree->opval.op = '+';
3436 tree->opval.op = '-';
3439 decorateType (parent, resultType);
3443 LRVAL (tree) = RRVAL (tree) = 1;
3444 /* if the left is a pointer */
3445 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3446 TETYPE (tree) = getSpec (TTYPE (tree) =
3450 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3451 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3452 TETYPE (tree) = getSpec (TTYPE (tree) =
3453 computeType (LTYPE (tree),
3461 /*------------------------------------------------------------------*/
3462 /*----------------------------*/
3464 /*----------------------------*/
3465 case '-': /* can be unary */
3466 /* if right is null then unary */
3470 if (!IS_ARITHMETIC (LTYPE (tree)))
3472 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3473 goto errorTreeReturn;
3476 /* if left is a literal then do it */
3477 if (IS_LITERAL (LTYPE (tree)))
3479 tree->type = EX_VALUE;
3480 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3482 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3485 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3486 TETYPE (tree) = getSpec (TTYPE (tree) =
3487 computeType (LTYPE (tree),
3495 /*------------------------------------------------------------------*/
3496 /*----------------------------*/
3498 /*----------------------------*/
3500 if (!(IS_PTR (LTYPE (tree)) ||
3501 IS_ARRAY (LTYPE (tree)) ||
3502 IS_ARITHMETIC (LTYPE (tree))))
3504 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3505 goto errorTreeReturn;
3508 if (!(IS_PTR (RTYPE (tree)) ||
3509 IS_ARRAY (RTYPE (tree)) ||
3510 IS_ARITHMETIC (RTYPE (tree))))
3512 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3513 goto errorTreeReturn;
3516 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3517 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3518 IS_INTEGRAL (RTYPE (tree))))
3520 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3521 goto errorTreeReturn;
3524 /* if they are both literal then */
3525 /* rewrite the tree */
3526 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3528 tree->type = EX_VALUE;
3529 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3530 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3531 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3532 valFromType (RETYPE (tree)));
3533 tree->right = tree->left = NULL;
3534 TETYPE (tree) = getSpec (TTYPE (tree) =
3535 tree->opval.val->type);
3539 /* if the left & right are equal then zero */
3540 if (isAstEqual (tree->left, tree->right))
3542 tree->type = EX_VALUE;
3543 tree->left = tree->right = NULL;
3544 tree->opval.val = constCharVal (0);
3545 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3549 /* if both of them are pointers or arrays then */
3550 /* the result is going to be an integer */
3551 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3552 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3553 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3555 /* if only the left is a pointer */
3556 /* then result is a pointer */
3557 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3558 TETYPE (tree) = getSpec (TTYPE (tree) =
3562 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3563 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3565 TETYPE (tree) = getSpec (TTYPE (tree) =
3566 computeType (LTYPE (tree),
3572 LRVAL (tree) = RRVAL (tree) = 1;
3574 /* if right is a literal and */
3575 /* left is also an addition/subtraction with a literal then */
3576 /* rearrange the tree */
3577 if (IS_LITERAL (RTYPE (tree))
3578 /* avoid infinite loop */
3579 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3581 ast *litTree, *litParent;
3582 litTree = searchLitOp (tree, &litParent, "+-");
3585 if (litTree->opval.op == '+')
3589 ast *tTree = litTree->left;
3590 litTree->left = litTree->right;
3591 litTree->right = tree->right;
3592 tree->right = tTree;
3593 tree->opval.op = '+';
3594 litTree->opval.op = '-';
3596 else if (litTree->opval.op == '-')
3598 if (IS_LITERAL (RTYPE (litTree)))
3602 ast *tTree = litTree->left;
3603 litTree->left = tree->right;
3604 tree->right = litParent->left;
3605 litParent->left = tTree;
3606 litTree->opval.op = '+';
3608 tree->decorated = 0;
3609 decorateType (tree, resultType);
3615 ast *tTree = litTree->right;
3616 litTree->right = tree->right;
3617 tree->right = tTree;
3620 decorateType (litParent, resultType);
3625 /*------------------------------------------------------------------*/
3626 /*----------------------------*/
3628 /*----------------------------*/
3630 /* can be only integral type */
3631 if (!IS_INTEGRAL (LTYPE (tree)))
3633 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3634 goto errorTreeReturn;
3637 /* if left is a literal then do it */
3638 if (IS_LITERAL (LTYPE (tree)))
3640 tree->type = EX_VALUE;
3641 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3643 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3644 return addCast (tree, resultTypeProp, TRUE);
3647 if (resultType == RESULT_TYPE_BIT &&
3648 IS_UNSIGNED (tree->left->etype) &&
3649 getSize (tree->left->etype) < INTSIZE)
3651 /* promotion rules are responsible for this strange result:
3652 bit -> int -> ~int -> bit
3653 uchar -> int -> ~int -> bit
3655 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3657 /* optimize bit-result, even if we optimize a buggy source */
3658 tree->type = EX_VALUE;
3659 tree->opval.val = constCharVal (1);
3662 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3664 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3667 /*------------------------------------------------------------------*/
3668 /*----------------------------*/
3670 /*----------------------------*/
3672 /* can be pointer */
3673 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3674 !IS_PTR (LTYPE (tree)) &&
3675 !IS_ARRAY (LTYPE (tree)))
3677 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3678 goto errorTreeReturn;
3681 /* if left is another '!' */
3682 if (IS_AST_NOT_OPER (tree->left))
3684 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3686 /* replace double '!!X' by 'X' */
3687 return tree->left->left;
3689 /* remove double '!!X' by 'X ? 1 : 0' */
3690 tree->opval.op = '?';
3691 tree->left = tree->left->left;
3692 tree->right = newNode (':',
3693 newAst_VALUE (constCharVal (1)),
3694 newAst_VALUE (constCharVal (0)));
3695 tree->right->filename = tree->filename;
3696 tree->right->lineno = tree->lineno;
3697 tree->decorated = 0;
3698 return decorateType (tree, resultType);
3701 /* if left is a literal then do it */
3702 if (IS_LITERAL (LTYPE (tree)))
3704 tree->type = EX_VALUE;
3705 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3707 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3711 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3714 /*------------------------------------------------------------------*/
3715 /*----------------------------*/
3717 /*----------------------------*/
3721 TTYPE (tree) = LTYPE (tree);
3722 TETYPE (tree) = LETYPE (tree);
3727 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3731 TTYPE (tree) = TETYPE (tree) = newCharLink();
3735 TTYPE (tree) = TETYPE (tree) = newIntLink();
3740 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3742 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3743 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3744 printTypeChain (LTYPE (tree), stderr);
3745 fprintf (stderr, ",");
3746 printTypeChain (RTYPE (tree), stderr);
3747 fprintf (stderr, "\n");
3748 goto errorTreeReturn;
3751 /* make smaller type only if it's a LEFT_OP */
3752 if (tree->opval.op == LEFT_OP)
3753 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3755 /* if they are both literal then */
3756 /* rewrite the tree */
3757 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3759 tree->type = EX_VALUE;
3760 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3761 valFromType (RETYPE (tree)),
3762 (tree->opval.op == LEFT_OP ? 1 : 0));
3763 tree->right = tree->left = NULL;
3764 TETYPE (tree) = getSpec (TTYPE (tree) =
3765 tree->opval.val->type);
3769 /* see if this is a GETBYTE operation if yes
3772 ast *otree = optimizeGetByte (tree, resultType);
3775 return decorateType (otree, RESULT_TYPE_NONE);
3778 /* see if this is a GETWORD operation if yes
3781 ast *otree = optimizeGetWord (tree, resultType);
3784 return decorateType (otree, RESULT_TYPE_NONE);
3787 LRVAL (tree) = RRVAL (tree) = 1;
3788 if (tree->opval.op == LEFT_OP)
3790 TETYPE (tree) = getSpec (TTYPE (tree) =
3791 computeType (LTYPE (tree),
3798 /* no promotion necessary */
3799 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3800 if (IS_LITERAL (TTYPE (tree)))
3801 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3804 /* if only the right side is a literal & we are
3805 shifting more than size of the left operand then zero */
3806 if (IS_LITERAL (RTYPE (tree)) &&
3807 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3808 (getSize (TETYPE (tree)) * 8))
3810 if (tree->opval.op==LEFT_OP ||
3811 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3813 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3814 (tree->opval.op == LEFT_OP ? "left" : "right"));
3815 tree->type = EX_VALUE;
3816 tree->left = tree->right = NULL;
3817 tree->opval.val = constCharVal (0);
3818 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3825 /*------------------------------------------------------------------*/
3826 /*----------------------------*/
3828 /*----------------------------*/
3829 case CAST: /* change the type */
3830 /* cannot cast to an aggregate type */
3831 if (IS_AGGREGATE (LTYPE (tree)))
3833 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3834 goto errorTreeReturn;
3837 /* make sure the type is complete and sane */
3838 changePointer(LTYPE(tree));
3839 checkTypeSanity(LETYPE(tree), "(cast)");
3842 /* if 'from' and 'to' are the same remove the superfluous cast,
3843 * this helps other optimizations */
3844 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3846 /* mark that the explicit cast has been removed,
3847 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3848 tree->right->values.removedCast = 1;
3852 /* If code memory is read only, then pointers to code memory */
3853 /* implicitly point to constants -- make this explicit */
3855 sym_link *t = LTYPE(tree);
3856 while (t && t->next)
3858 if (IS_CODEPTR(t) && port->mem.code_ro)
3860 if (IS_SPEC(t->next))
3861 SPEC_CONST (t->next) = 1;
3863 DCL_PTR_CONST (t->next) = 1;
3870 /* if the right is a literal replace the tree */
3871 if (IS_LITERAL (RETYPE (tree))) {
3872 if (!IS_PTR (LTYPE (tree))) {
3873 tree->type = EX_VALUE;
3875 valCastLiteral (LTYPE (tree),
3876 floatFromVal (valFromType (RETYPE (tree))));
3879 TTYPE (tree) = tree->opval.val->type;
3880 tree->values.literalFromCast = 1;
3881 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3882 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3883 sym_link *rest = LTYPE(tree)->next;
3884 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3885 TTYPE(tree) = newLink(DECLARATOR);
3886 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3887 TTYPE(tree)->next = rest;
3888 tree->left->opval.lnk = TTYPE(tree);
3891 TTYPE (tree) = LTYPE (tree);
3895 TTYPE (tree) = LTYPE (tree);
3899 #if 0 // this is already checked, now this could be explicit
3900 /* if pointer to struct then check names */
3901 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3902 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3903 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3905 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3906 SPEC_STRUCT(LETYPE(tree))->tag);
3909 if (IS_ADDRESS_OF_OP(tree->right)
3910 && IS_AST_SYM_VALUE (tree->right->left)
3911 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3913 symbol * sym = AST_SYMBOL (tree->right->left);
3914 unsigned int gptype = 0;
3915 unsigned int addr = SPEC_ADDR (sym->etype);
3917 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3918 || TARGET_IS_PIC16) )
3920 switch (SPEC_SCLS (sym->etype))
3923 gptype = GPTYPE_CODE;
3926 gptype = GPTYPE_FAR;
3930 gptype = GPTYPE_NEAR;
3933 gptype = GPTYPE_XSTACK;
3938 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3939 gptype = GPTYPE_NEAR;
3941 addr |= gptype << (8*(GPTRSIZE - 1));
3944 tree->type = EX_VALUE;
3946 valCastLiteral (LTYPE (tree), addr);
3947 TTYPE (tree) = tree->opval.val->type;
3948 TETYPE (tree) = getSpec (TTYPE (tree));
3951 tree->values.literalFromCast = 1;
3955 /* handle offsetof macro: */
3956 /* #define offsetof(TYPE, MEMBER) \ */
3957 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3958 if (IS_ADDRESS_OF_OP(tree->right)
3959 && IS_AST_OP (tree->right->left)
3960 && tree->right->left->opval.op == PTR_OP
3961 && IS_AST_OP (tree->right->left->left)
3962 && tree->right->left->left->opval.op == CAST
3963 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3965 symbol *element = getStructElement (
3966 SPEC_STRUCT (LETYPE(tree->right->left)),
3967 AST_SYMBOL(tree->right->left->right)
3971 tree->type = EX_VALUE;
3972 tree->opval.val = valCastLiteral (
3975 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3978 TTYPE (tree) = tree->opval.val->type;
3979 TETYPE (tree) = getSpec (TTYPE (tree));
3986 /* if the right is a literal replace the tree */
3987 if (IS_LITERAL (RETYPE (tree))) {
3989 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3990 /* rewrite (type *)litaddr
3992 and define type at litaddr temp
3993 (but only if type's storage class is not generic)
3995 ast *newTree = newNode ('&', NULL, NULL);
3998 TTYPE (newTree) = LTYPE (tree);
3999 TETYPE (newTree) = getSpec(LTYPE (tree));
4001 /* define a global symbol at the casted address*/
4002 sym = newSymbol(genSymName (0), 0);
4003 sym->type = LTYPE (tree)->next;
4005 sym->type = newLink (V_VOID);
4006 sym->etype = getSpec(sym->type);
4007 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4008 sym->lineDef = tree->lineno;
4011 SPEC_STAT (sym->etype) = 1;
4012 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4013 SPEC_ABSA(sym->etype) = 1;
4014 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4017 newTree->left = newAst_VALUE(symbolVal(sym));
4018 newTree->left->filename = tree->filename;
4019 newTree->left->lineno = tree->lineno;
4020 LTYPE (newTree) = sym->type;
4021 LETYPE (newTree) = sym->etype;
4022 LLVAL (newTree) = 1;
4023 LRVAL (newTree) = 0;
4024 TLVAL (newTree) = 1;
4028 if (!IS_PTR (LTYPE (tree))) {
4029 tree->type = EX_VALUE;
4031 valCastLiteral (LTYPE (tree),
4032 floatFromVal (valFromType (RTYPE (tree))));
4033 TTYPE (tree) = tree->opval.val->type;
4036 tree->values.literalFromCast = 1;
4037 TETYPE (tree) = getSpec (TTYPE (tree));
4041 TTYPE (tree) = LTYPE (tree);
4045 TETYPE (tree) = getSpec (TTYPE (tree));
4049 /*------------------------------------------------------------------*/
4050 /*----------------------------*/
4051 /* logical &&, || */
4052 /*----------------------------*/
4055 /* each must be arithmetic type or be a pointer */
4056 if (!IS_PTR (LTYPE (tree)) &&
4057 !IS_ARRAY (LTYPE (tree)) &&
4058 !IS_INTEGRAL (LTYPE (tree)))
4060 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4061 goto errorTreeReturn;
4064 if (!IS_PTR (RTYPE (tree)) &&
4065 !IS_ARRAY (RTYPE (tree)) &&
4066 !IS_INTEGRAL (RTYPE (tree)))
4068 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4069 goto errorTreeReturn;
4071 /* if they are both literal then */
4072 /* rewrite the tree */
4073 if (IS_LITERAL (RTYPE (tree)) &&
4074 IS_LITERAL (LTYPE (tree)))
4076 tree->type = EX_VALUE;
4077 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4078 valFromType (RTYPE (tree)),
4080 tree->right = tree->left = NULL;
4081 TETYPE (tree) = getSpec (TTYPE (tree) =
4082 tree->opval.val->type);
4085 LRVAL (tree) = RRVAL (tree) = 1;
4086 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4089 /*------------------------------------------------------------------*/
4090 /*----------------------------*/
4091 /* comparison operators */
4092 /*----------------------------*/
4100 ast *lt = optimizeCompare (tree);
4106 /* if they are pointers they must be castable */
4107 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4109 if (tree->opval.op==EQ_OP &&
4110 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4111 // we cannot cast a gptr to a !gptr: switch the leaves
4112 struct ast *s=tree->left;
4113 tree->left=tree->right;
4116 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4118 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4119 fprintf (stderr, "comparing type ");
4120 printTypeChain (LTYPE (tree), stderr);
4121 fprintf (stderr, "to type ");
4122 printTypeChain (RTYPE (tree), stderr);
4123 fprintf (stderr, "\n");
4124 goto errorTreeReturn;
4127 /* else they should be promotable to one another */
4130 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4131 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4133 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4135 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4136 fprintf (stderr, "comparing type ");
4137 printTypeChain (LTYPE (tree), stderr);
4138 fprintf (stderr, "to type ");
4139 printTypeChain (RTYPE (tree), stderr);
4140 fprintf (stderr, "\n");
4141 goto errorTreeReturn;
4146 CCR_RESULT ccr_result = CCR_OK;
4148 /* if left is integral and right is literal
4149 then check constant range */
4150 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4151 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4152 tree->opval.op, FALSE);
4153 if (ccr_result == CCR_OK &&
4154 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4155 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4156 tree->opval.op, TRUE);
4159 case CCR_ALWAYS_TRUE:
4160 case CCR_ALWAYS_FALSE:
4161 if (!options.lessPedantic)
4162 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4163 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4164 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4171 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4172 if (tree->opval.op == '>' &&
4173 SPEC_USIGN(LETYPE(tree)) &&
4174 IS_LITERAL(RTYPE(tree)) &&
4175 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4177 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4179 /* the parent is an ifx: */
4180 /* if (unsigned value) */
4184 /* (unsigned value) ? 1 : 0 */
4185 tree->opval.op = '?';
4186 tree->right = newNode (':',
4187 newAst_VALUE (constCharVal (1)),
4188 tree->right); /* val 0 */
4189 tree->right->filename = tree->filename;
4190 tree->right->lineno = tree->lineno;
4191 tree->right->left->filename = tree->filename;
4192 tree->right->left->lineno = tree->lineno;
4193 tree->decorated = 0;
4194 return decorateType (tree, resultType);
4197 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4198 if (IS_LITERAL(RTYPE(tree)) &&
4199 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4200 tree->opval.op == EQ_OP &&
4201 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4203 tree->opval.op = '!';
4205 tree->decorated = 0;
4206 return decorateType (tree, resultType);
4209 /* if they are both literal then */
4210 /* rewrite the tree */
4211 if (IS_LITERAL (RTYPE (tree)) &&
4212 IS_LITERAL (LTYPE (tree)))
4214 tree->type = EX_VALUE;
4215 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4216 valFromType (RETYPE (tree)),
4218 tree->right = tree->left = NULL;
4219 TETYPE (tree) = getSpec (TTYPE (tree) =
4220 tree->opval.val->type);
4224 /* if one is 'signed char ' and the other one is 'unsigned char' */
4225 /* it's necessary to promote to int */
4226 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4227 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4229 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4230 if it's possible to use a 'signed char' */
4232 /* is left a 'unsigned char'? */
4233 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4234 /* the value range of a 'unsigned char' is 0...255;
4235 if the actual value is < 128 it can be changed to signed */
4236 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4238 /* now we've got 2 'signed char'! */
4239 SPEC_USIGN (RETYPE (tree)) = 0;
4241 /* same test for the left operand: */
4242 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4243 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4245 SPEC_USIGN (LETYPE (tree)) = 0;
4249 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4250 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4251 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4255 LRVAL (tree) = RRVAL (tree) = 1;
4256 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4258 /* condition transformations */
4260 unsigned transformedOp = 0;
4262 switch (tree->opval.op)
4264 case '<': /* transform (a < b) to !(a >= b) */
4266 transformedOp = GE_OP;
4268 case '>': /* transform (a > b) to !(a <= b) */
4270 transformedOp = LE_OP;
4272 case LE_OP: /* transform (a <= b) to !(a > b) */
4274 transformedOp = '>';
4276 case GE_OP: /* transform (a >= b) to !(a < b) */
4278 transformedOp = '<';
4280 case NE_OP: /* transform (a != b) to !(a == b) */
4282 transformedOp = EQ_OP;
4284 case EQ_OP: /* transform (a == b) to !(a != b) */
4286 transformedOp = NE_OP;
4293 tree->opval.op = transformedOp;
4294 tree->decorated = 0;
4295 tree = newNode ('!', tree, NULL);
4296 tree->filename = tree->left->filename;
4297 tree->lineno = tree->left->lineno;
4298 return decorateType (tree, resultType);
4304 /*------------------------------------------------------------------*/
4305 /*----------------------------*/
4307 /*----------------------------*/
4308 case SIZEOF: /* evaluate wihout code generation */
4309 /* change the type to a integer */
4311 int size = getSize (tree->right->ftype);
4313 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4314 if (!size && !IS_VOID(tree->right->ftype))
4315 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4317 tree->type = EX_VALUE;
4318 tree->opval.val = constVal (buffer);
4319 tree->right = tree->left = NULL;
4320 TETYPE (tree) = getSpec (TTYPE (tree) =
4321 tree->opval.val->type);
4325 /*------------------------------------------------------------------*/
4326 /*----------------------------*/
4328 /*----------------------------*/
4330 /* return typeof enum value */
4331 tree->type = EX_VALUE;
4334 if (IS_SPEC(tree->right->ftype)) {
4335 switch (SPEC_NOUN(tree->right->ftype)) {
4337 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4338 else typeofv = TYPEOF_INT;
4341 typeofv = TYPEOF_FLOAT;
4344 typeofv = TYPEOF_FIXED16X16;
4347 typeofv = TYPEOF_CHAR;
4350 typeofv = TYPEOF_VOID;
4353 typeofv = TYPEOF_STRUCT;
4356 typeofv = TYPEOF_BITFIELD;
4359 typeofv = TYPEOF_BIT;
4362 typeofv = TYPEOF_SBIT;
4368 switch (DCL_TYPE(tree->right->ftype)) {
4370 typeofv = TYPEOF_POINTER;
4373 typeofv = TYPEOF_FPOINTER;
4376 typeofv = TYPEOF_CPOINTER;
4379 typeofv = TYPEOF_GPOINTER;
4382 typeofv = TYPEOF_PPOINTER;
4385 typeofv = TYPEOF_IPOINTER;
4388 typeofv = TYPEOF_ARRAY;
4391 typeofv = TYPEOF_FUNCTION;
4397 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4398 tree->opval.val = constVal (buffer);
4399 tree->right = tree->left = NULL;
4400 TETYPE (tree) = getSpec (TTYPE (tree) =
4401 tree->opval.val->type);
4404 /*------------------------------------------------------------------*/
4405 /*----------------------------*/
4406 /* conditional operator '?' */
4407 /*----------------------------*/
4409 /* the type is value of the colon operator (on the right) */
4410 assert (IS_COLON_OP (tree->right));
4412 /* If already known then replace the tree : optimizer will do it
4413 but faster to do it here. If done before decorating tree->right
4414 this can save generating unused const strings. */
4415 if (IS_LITERAL (LTYPE (tree)))
4417 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4418 return decorateType (tree->right->left, resultTypeProp);
4420 return decorateType (tree->right->right, resultTypeProp);
4423 tree->right = decorateType (tree->right, resultTypeProp);
4425 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4426 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4428 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4429 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4431 if ((valTrue != 0) && (valFalse == 0))
4433 /* assign cond to result */
4434 tree->left->decorated = 0;
4435 return decorateType (tree->left, resultTypeProp);
4437 else if ((valTrue == 0) && (valFalse != 0))
4439 /* assign !cond to result */
4440 tree->opval.op = '!';
4441 tree->decorated = 0;
4443 return decorateType (tree, resultTypeProp);
4447 /* they have the same boolean value, make them equal */
4448 tree->right->left = tree->right->right;
4452 /* if they are equal then replace the tree */
4453 if (isAstEqual (tree->right->left, tree->right->right))
4455 return tree->right->left;
4458 TTYPE (tree) = RTYPE (tree);
4459 TETYPE (tree) = getSpec (TTYPE (tree));
4463 /* if they don't match we have a problem */
4464 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4465 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4467 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4468 goto errorTreeReturn;
4471 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4472 resultType, tree->opval.op);
4473 TETYPE (tree) = getSpec (TTYPE (tree));
4477 #if 0 // assignment operators are converted by the parser
4478 /*------------------------------------------------------------------*/
4479 /*----------------------------*/
4480 /* assignment operators */
4481 /*----------------------------*/
4484 /* for these it must be both must be integral */
4485 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4486 !IS_ARITHMETIC (RTYPE (tree)))
4488 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4489 goto errorTreeReturn;
4492 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4494 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4495 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4499 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4500 goto errorTreeReturn;
4511 /* for these it must be both must be integral */
4512 if (!IS_INTEGRAL (LTYPE (tree)) ||
4513 !IS_INTEGRAL (RTYPE (tree)))
4515 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4516 goto errorTreeReturn;
4519 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4521 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4522 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4526 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4527 goto errorTreeReturn;
4533 /*------------------------------------------------------------------*/
4534 /*----------------------------*/
4536 /*----------------------------*/
4538 if (!(IS_PTR (LTYPE (tree)) ||
4539 IS_ARITHMETIC (LTYPE (tree))))
4541 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4542 goto errorTreeReturn;
4545 if (!(IS_PTR (RTYPE (tree)) ||
4546 IS_ARITHMETIC (RTYPE (tree))))
4548 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4549 goto errorTreeReturn;
4552 TETYPE (tree) = getSpec (TTYPE (tree) =
4553 computeType (LTYPE (tree),
4558 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4559 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4563 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4564 goto errorTreeReturn;
4570 /*------------------------------------------------------------------*/
4571 /*----------------------------*/
4573 /*----------------------------*/
4575 /* this is not a unary operation */
4576 /* if both pointers then problem */
4577 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4579 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4580 goto errorTreeReturn;
4583 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4585 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4586 goto errorTreeReturn;
4589 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4591 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4592 goto errorTreeReturn;
4595 TETYPE (tree) = getSpec (TTYPE (tree) =
4596 computeType (LTYPE (tree),
4601 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4602 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4606 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4607 goto errorTreeReturn;
4610 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4611 tree->opval.op = '=';
4616 /*------------------------------------------------------------------*/
4617 /*----------------------------*/
4618 /* straight assignemnt */
4619 /*----------------------------*/
4621 /* cannot be an aggregate */
4622 if (IS_AGGREGATE (LTYPE (tree)))
4624 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4625 goto errorTreeReturn;
4628 /* they should either match or be castable */
4629 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4631 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4632 printFromToType(RTYPE(tree),LTYPE(tree));
4635 /* if the left side of the tree is of type void
4636 then report error */
4637 if (IS_VOID (LTYPE (tree)))
4639 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4640 printFromToType(RTYPE(tree), LTYPE(tree));
4643 TETYPE (tree) = getSpec (TTYPE (tree) =
4647 if (!tree->initMode ) {
4648 if (IS_CONSTANT(LTYPE(tree)))
4649 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4653 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4654 goto errorTreeReturn;
4659 /*------------------------------------------------------------------*/
4660 /*----------------------------*/
4661 /* comma operator */
4662 /*----------------------------*/
4664 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4667 /*------------------------------------------------------------------*/
4668 /*----------------------------*/
4670 /*----------------------------*/
4673 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4674 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4676 if (tree->left->opval.op == '*' && !tree->left->right)
4677 tree->left = tree->left->left;
4680 /* require a function or pointer to function */
4681 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4683 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4684 goto errorTreeReturn;
4687 /* if there are parms, make sure that
4688 parms are decorate / process / reverse only once */
4690 !tree->right->decorated)
4695 if (IS_FUNCPTR (LTYPE (tree)))
4697 functype = LTYPE (tree)->next;
4698 processFuncPtrArgs (functype);
4701 functype = LTYPE (tree);
4703 if (processParms (tree->left, FUNC_ARGS(functype),
4704 &tree->right, &parmNumber, TRUE))
4706 goto errorTreeReturn;
4709 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4710 !IFFUNC_ISBUILTIN(functype))
4712 reverseParms (tree->right);
4715 TTYPE (tree) = functype->next;
4716 TETYPE (tree) = getSpec (TTYPE (tree));
4720 /*------------------------------------------------------------------*/
4721 /*----------------------------*/
4722 /* return statement */
4723 /*----------------------------*/
4728 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4730 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4731 printFromToType (RTYPE(tree), currFunc->type->next);
4732 goto errorTreeReturn;
4735 if (IS_VOID (currFunc->type->next)
4737 !IS_VOID (RTYPE (tree)))
4739 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4740 goto errorTreeReturn;
4743 /* if there is going to be a casting required then add it */
4744 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4747 decorateType (newNode (CAST,
4748 newAst_LINK (copyLinkChain (currFunc->type->next)),
4758 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4760 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4761 goto errorTreeReturn;
4764 TTYPE (tree) = TETYPE (tree) = NULL;
4767 /*------------------------------------------------------------------*/
4768 /*----------------------------*/
4769 /* switch statement */
4770 /*----------------------------*/
4772 /* the switch value must be an integer */
4773 if (!IS_INTEGRAL (LTYPE (tree)))
4775 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4776 goto errorTreeReturn;
4779 TTYPE (tree) = TETYPE (tree) = NULL;
4782 /*------------------------------------------------------------------*/
4783 /*----------------------------*/
4785 /*----------------------------*/
4787 tree->left = backPatchLabels (tree->left,
4790 TTYPE (tree) = TETYPE (tree) = NULL;
4793 /*------------------------------------------------------------------*/
4794 /*----------------------------*/
4796 /*----------------------------*/
4799 AST_FOR (tree, initExpr) = decorateType (
4800 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4801 AST_FOR (tree, condExpr) = decorateType (
4802 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4803 AST_FOR (tree, loopExpr) = decorateType (
4804 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4806 /* if the for loop is reversible then
4807 reverse it otherwise do what we normally
4813 if (isLoopReversible (tree, &sym, &init, &end))
4814 return reverseLoop (tree, sym, init, end);
4816 return decorateType (createFor (AST_FOR (tree, trueLabel),
4817 AST_FOR (tree, continueLabel),
4818 AST_FOR (tree, falseLabel),
4819 AST_FOR (tree, condLabel),
4820 AST_FOR (tree, initExpr),
4821 AST_FOR (tree, condExpr),
4822 AST_FOR (tree, loopExpr),
4823 tree->left), RESULT_TYPE_NONE);
4826 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4827 "node PARAM shouldn't be processed here");
4828 /* but in processParams() */
4831 TTYPE (tree) = TETYPE (tree) = NULL;
4835 /* some error found this tree will be killed */
4837 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4838 tree->opval.op = NULLOP;
4844 /*-----------------------------------------------------------------*/
4845 /* sizeofOp - processes size of operation */
4846 /*-----------------------------------------------------------------*/
4848 sizeofOp (sym_link * type)
4853 /* make sure the type is complete and sane */
4854 checkTypeSanity(type, "(sizeof)");
4856 /* get the size and convert it to character */
4857 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4858 if (!size && !IS_VOID(type))
4859 werror (E_SIZEOF_INCOMPLETE_TYPE);
4861 /* now convert into value */
4862 return constVal (buff);
4866 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4867 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4868 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4869 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4870 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4871 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4872 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4874 /*-----------------------------------------------------------------*/
4875 /* backPatchLabels - change and or not operators to flow control */
4876 /*-----------------------------------------------------------------*/
4878 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4884 /* while-loops insert a label between the IFX and the condition,
4885 therefore look behind the label too */
4886 if (tree->opval.op == LABEL &&
4888 IS_ANDORNOT (tree->right))
4890 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4894 if (!(IS_ANDORNOT (tree)))
4897 /* if this an and */
4900 static int localLbl = 0;
4903 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4904 localLabel = newSymbol (buffer, NestLevel);
4906 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4908 /* if left is already a IFX then just change the if true label in that */
4909 if (!IS_IFX (tree->left))
4910 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4912 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4913 /* right is a IFX then just join */
4914 if (IS_IFX (tree->right))
4915 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4917 tree->right = createLabel (localLabel, tree->right);
4918 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4920 return newNode (NULLOP, tree->left, tree->right);
4923 /* if this is an or operation */
4926 static int localLbl = 0;
4929 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4930 localLabel = newSymbol (buffer, NestLevel);
4932 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4934 /* if left is already a IFX then just change the if true label in that */
4935 if (!IS_IFX (tree->left))
4936 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4938 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4939 /* right is a IFX then just join */
4940 if (IS_IFX (tree->right))
4941 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4943 tree->right = createLabel (localLabel, tree->right);
4944 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4946 return newNode (NULLOP, tree->left, tree->right);
4952 /* call with exchanged labels */
4953 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4955 /* if left isn't already a IFX */
4956 if (!IS_IFX (tree->left))
4958 tree->left = newNode (IFX, tree->left, NULL);
4959 tree->left->trueLabel = falseLabel;
4960 tree->left->falseLabel = trueLabel;
4967 tree->trueLabel = trueLabel;
4968 tree->falseLabel = falseLabel;
4975 /*-----------------------------------------------------------------*/
4976 /* createBlock - create expression tree for block */
4977 /*-----------------------------------------------------------------*/
4979 createBlock (symbol * decl, ast * body)
4983 /* if the block has nothing */
4987 ex = newNode (BLOCK, NULL, body);
4988 ex->values.sym = decl;
4991 ex->filename = NULL;
4996 /*-----------------------------------------------------------------*/
4997 /* createLabel - creates the expression tree for labels */
4998 /*-----------------------------------------------------------------*/
5000 createLabel (symbol * label, ast * stmnt)
5003 char name[SDCC_NAME_MAX + 1];
5006 /* must create fresh symbol if the symbol name */
5007 /* exists in the symbol table, since there can */
5008 /* be a variable with the same name as the labl */
5009 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5010 (csym->level == label->level))
5011 label = newSymbol (label->name, label->level);
5013 /* change the name before putting it in add _ */
5014 SNPRINTF(name, sizeof(name), "%s", label->name);
5016 /* put the label in the LabelSymbol table */
5017 /* but first check if a label of the same */
5019 if ((csym = findSym (LabelTab, NULL, name)))
5020 werror (E_DUPLICATE_LABEL, label->name);
5022 addSym (LabelTab, label, name, label->level, 0, 0);
5026 label->key = labelKey++;
5027 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5028 rValue->filename = NULL;
5034 /*-----------------------------------------------------------------*/
5035 /* createCase - generates the parsetree for a case statement */
5036 /*-----------------------------------------------------------------*/
5038 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5040 char caseLbl[SDCC_NAME_MAX + 1];
5044 /* if the switch statement does not exist */
5045 /* then case is out of context */
5048 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5052 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5053 /* if not a constant then error */
5054 if (!IS_LITERAL (caseVal->ftype))
5056 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5060 /* if not a integer than error */
5061 if (!IS_INTEGRAL (caseVal->ftype))
5063 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5067 /* find the end of the switch values chain */
5068 if (!(val = swStat->values.switchVals.swVals))
5069 swStat->values.switchVals.swVals = caseVal->opval.val;
5072 /* also order the cases according to value */
5074 int cVal = (int) ulFromVal (caseVal->opval.val);
5075 while (val && (int) ulFromVal (val) < cVal)
5081 /* if we reached the end then */
5084 pval->next = caseVal->opval.val;
5086 else if ((int) ulFromVal (val) == cVal)
5088 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5094 /* we found a value greater than */
5095 /* the current value we must add this */
5096 /* before the value */
5097 caseVal->opval.val->next = val;
5099 /* if this was the first in chain */
5100 if (swStat->values.switchVals.swVals == val)
5101 swStat->values.switchVals.swVals =
5104 pval->next = caseVal->opval.val;
5109 /* create the case label */
5110 SNPRINTF(caseLbl, sizeof(caseLbl),
5112 swStat->values.switchVals.swNum,
5113 (int) ulFromVal (caseVal->opval.val));
5115 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5116 rexpr->filename = 0;
5121 /*-----------------------------------------------------------------*/
5122 /* createDefault - creates the parse tree for the default statement */
5123 /*-----------------------------------------------------------------*/
5125 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5127 char defLbl[SDCC_NAME_MAX + 1];
5129 /* if the switch statement does not exist */
5130 /* then case is out of context */
5133 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5137 if (swStat->values.switchVals.swDefault)
5139 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5144 /* turn on the default flag */
5145 swStat->values.switchVals.swDefault = 1;
5147 /* create the label */
5148 SNPRINTF (defLbl, sizeof(defLbl),
5149 "_default_%d", swStat->values.switchVals.swNum);
5150 return createLabel (newSymbol (defLbl, 0), stmnt);
5153 /*-----------------------------------------------------------------*/
5154 /* createIf - creates the parsetree for the if statement */
5155 /*-----------------------------------------------------------------*/
5157 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5159 static int Lblnum = 0;
5161 symbol *ifTrue, *ifFalse, *ifEnd;
5163 /* if neither exists */
5164 if (!elseBody && !ifBody) {
5165 // if there are no side effects (i++, j() etc)
5166 if (!hasSEFcalls(condAst)) {
5171 /* create the labels */
5172 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5173 ifFalse = newSymbol (buffer, NestLevel);
5174 /* if no else body then end == false */
5179 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5180 ifEnd = newSymbol (buffer, NestLevel);
5183 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5184 ifTrue = newSymbol (buffer, NestLevel);
5188 /* attach the ifTrue label to the top of it body */
5189 ifBody = createLabel (ifTrue, ifBody);
5190 /* attach a goto end to the ifBody if else is present */
5193 ifBody = newNode (NULLOP, ifBody,
5195 newAst_VALUE (symbolVal (ifEnd)),
5197 /* put the elseLabel on the else body */
5198 elseBody = createLabel (ifFalse, elseBody);
5199 /* out the end at the end of the body */
5200 elseBody = newNode (NULLOP,
5202 createLabel (ifEnd, NULL));
5206 ifBody = newNode (NULLOP, ifBody,
5207 createLabel (ifFalse, NULL));
5209 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5210 if (IS_IFX (condAst))
5213 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5215 return newNode (NULLOP, ifTree,
5216 newNode (NULLOP, ifBody, elseBody));
5220 /*-----------------------------------------------------------------*/
5221 /* createDo - creates parse tree for do */
5224 /* _docontinue_n: */
5225 /* condition_expression +-> trueLabel -> _dobody_n */
5227 /* +-> falseLabel-> _dobreak_n */
5229 /*-----------------------------------------------------------------*/
5231 createDo (symbol * trueLabel, symbol * continueLabel,
5232 symbol * falseLabel, ast * condAst, ast * doBody)
5237 /* if the body does not exist then it is simple */
5240 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5241 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5242 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5243 doTree->trueLabel = continueLabel;
5244 doTree->falseLabel = NULL;
5246 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5250 /* otherwise we have a body */
5251 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5253 /* attach the body label to the top */
5254 doBody = createLabel (trueLabel, doBody);
5255 /* attach the continue label to end of body */
5256 doBody = newNode (NULLOP, doBody,
5257 createLabel (continueLabel, NULL));
5259 /* now put the break label at the end */
5260 if (IS_IFX (condAst))
5263 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5265 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5267 /* putting it together */
5268 return newNode (NULLOP, doBody, doTree);
5271 /*-----------------------------------------------------------------*/
5272 /* createFor - creates parse tree for 'for' statement */
5275 /* condExpr +-> trueLabel -> _forbody_n */
5277 /* +-> falseLabel-> _forbreak_n */
5280 /* _forcontinue_n: */
5282 /* goto _forcond_n ; */
5284 /*-----------------------------------------------------------------*/
5286 createFor (symbol * trueLabel, symbol * continueLabel,
5287 symbol * falseLabel, symbol * condLabel,
5288 ast * initExpr, ast * condExpr, ast * loopExpr,
5293 /* if loopexpression not present then we can generate it */
5294 /* the same way as a while */
5296 return newNode (NULLOP, initExpr,
5297 createWhile (trueLabel, continueLabel,
5298 falseLabel, condExpr, forBody));
5299 /* vanilla for statement */
5300 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5302 if (condExpr && !IS_IFX (condExpr))
5303 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5306 /* attach condition label to condition */
5307 condExpr = createLabel (condLabel, condExpr);
5309 /* attach body label to body */
5310 forBody = createLabel (trueLabel, forBody);
5312 /* attach continue to forLoop expression & attach */
5313 /* goto the forcond @ and of loopExpression */
5314 loopExpr = createLabel (continueLabel,
5318 newAst_VALUE (symbolVal (condLabel)),
5320 /* now start putting them together */
5321 forTree = newNode (NULLOP, initExpr, condExpr);
5322 forTree = newNode (NULLOP, forTree, forBody);
5323 forTree = newNode (NULLOP, forTree, loopExpr);
5324 /* finally add the break label */
5325 forTree = newNode (NULLOP, forTree,
5326 createLabel (falseLabel, NULL));
5330 /*-----------------------------------------------------------------*/
5331 /* createWhile - creates parse tree for while statement */
5332 /* the while statement will be created as follows */
5334 /* _while_continue_n: */
5335 /* condition_expression +-> trueLabel -> _while_boby_n */
5337 /* +-> falseLabel -> _while_break_n */
5338 /* _while_body_n: */
5340 /* goto _while_continue_n */
5341 /* _while_break_n: */
5342 /*-----------------------------------------------------------------*/
5344 createWhile (symbol * trueLabel, symbol * continueLabel,
5345 symbol * falseLabel, ast * condExpr, ast * whileBody)
5349 /* put the continue label */
5350 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5351 condExpr = createLabel (continueLabel, condExpr);
5352 condExpr->filename = NULL;
5353 condExpr->lineno = 0;
5355 /* put the body label in front of the body */
5356 whileBody = createLabel (trueLabel, whileBody);
5357 whileBody->filename = NULL;
5358 whileBody->lineno = 0;
5359 /* put a jump to continue at the end of the body */
5360 /* and put break label at the end of the body */
5361 whileBody = newNode (NULLOP,
5364 newAst_VALUE (symbolVal (continueLabel)),
5365 createLabel (falseLabel, NULL)));
5367 /* put it all together */
5368 if (IS_IFX (condExpr))
5369 whileTree = condExpr;
5372 whileTree = newNode (IFX, condExpr, NULL);
5373 /* put the true & false labels in place */
5374 whileTree->trueLabel = trueLabel;
5375 whileTree->falseLabel = falseLabel;
5378 return newNode (NULLOP, whileTree, whileBody);
5381 /*-----------------------------------------------------------------*/
5382 /* isShiftRightLitVal _BitAndLitVal - helper function */
5383 /*-----------------------------------------------------------------*/
5385 isShiftRightLitVal_BitAndLitVal (ast * tree)
5387 /* if this is not a bit and */
5388 if (!IS_BITAND (tree))
5391 /* will look for tree of the form
5392 ( expr >> litval2) & litval1 */
5393 if (!IS_AST_LIT_VALUE (tree->right))
5396 if (!IS_RIGHT_OP (tree->left))
5399 if (!IS_AST_LIT_VALUE (tree->left->right))
5402 return tree->left->left;
5405 /*-----------------------------------------------------------------*/
5406 /* isBitAndPowOf2 - helper function */
5407 /*-----------------------------------------------------------------*/
5409 isBitAndPow2 (ast * tree)
5411 /* if this is not a bit and */
5412 if (!IS_BITAND (tree))
5415 /* will look for tree of the form
5416 ( expr & (1 << litval) */
5417 if (!IS_AST_LIT_VALUE (tree->right))
5420 return powof2 (AST_ULONG_VALUE (tree->right));
5423 /*-----------------------------------------------------------------*/
5424 /* optimizeGetHbit - get highest order bit of the expression */
5425 /*-----------------------------------------------------------------*/
5427 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5432 expr = isShiftRightLitVal_BitAndLitVal(tree);
5435 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5436 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5437 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5440 if (!expr && (resultType == RESULT_TYPE_BIT))
5443 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5449 /* make sure the port supports GETHBIT */
5450 if (port->hasExtBitOp
5451 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5454 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5457 /*-----------------------------------------------------------------*/
5458 /* optimizeGetAbit - get a single bit of the expression */
5459 /*-----------------------------------------------------------------*/
5461 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5466 expr = isShiftRightLitVal_BitAndLitVal(tree);
5469 if (AST_ULONG_VALUE (tree->right) != 1)
5471 count = tree->left->right;
5473 if (!expr && (resultType == RESULT_TYPE_BIT))
5475 int p2 = isBitAndPow2 (tree);
5479 count = newAst_VALUE (valueFromLit (p2));
5485 /* make sure the port supports GETABIT */
5486 if (port->hasExtBitOp
5487 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5490 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5494 /*-----------------------------------------------------------------*/
5495 /* optimizeGetByte - get a byte of the expression */
5496 /*-----------------------------------------------------------------*/
5498 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5504 expr = isShiftRightLitVal_BitAndLitVal(tree);
5507 i = AST_ULONG_VALUE (tree->left->right);
5508 count = tree->left->right;
5509 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5512 if (!expr && resultType == RESULT_TYPE_CHAR)
5514 /* if this is a right shift over a multiple of 8 */
5515 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5517 i = AST_ULONG_VALUE (tree->right);
5518 count = tree->right;
5522 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5525 /* make sure the port supports GETBYTE */
5526 if (port->hasExtBitOp
5527 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5530 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5533 /*-----------------------------------------------------------------*/
5534 /* optimizeGetWord - get two bytes of the expression */
5535 /*-----------------------------------------------------------------*/
5537 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5543 expr = isShiftRightLitVal_BitAndLitVal(tree);
5546 i = AST_ULONG_VALUE (tree->left->right);
5547 count = tree->left->right;
5548 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5551 if (!expr && resultType == RESULT_TYPE_INT)
5553 /* if this is a right shift over a multiple of 8 */
5554 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5556 i = AST_ULONG_VALUE (tree->right);
5557 count = tree->right;
5561 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5564 /* make sure the port supports GETWORD */
5565 if (port->hasExtBitOp
5566 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5569 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5572 /*-----------------------------------------------------------------*/
5573 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5574 /*-----------------------------------------------------------------*/
5576 optimizeRRCRLC (ast * root)
5578 /* will look for trees of the form
5579 (?expr << 1) | (?expr >> 7) or
5580 (?expr >> 7) | (?expr << 1) will make that
5581 into a RLC : operation ..
5583 (?expr >> 1) | (?expr << 7) or
5584 (?expr << 7) | (?expr >> 1) will make that
5585 into a RRC operation
5586 note : by 7 I mean (number of bits required to hold the
5588 /* if the root operation is not a | operation then not */
5589 if (!IS_BITOR (root))
5592 /* I have to think of a better way to match patterns this sucks */
5593 /* that aside let's start looking for the first case : I use a
5594 negative check a lot to improve the efficiency */
5595 /* (?expr << 1) | (?expr >> 7) */
5596 if (IS_LEFT_OP (root->left) &&
5597 IS_RIGHT_OP (root->right))
5600 if (!SPEC_USIGN (TETYPE (root->left->left)))
5603 if (!IS_AST_LIT_VALUE (root->left->right) ||
5604 !IS_AST_LIT_VALUE (root->right->right))
5607 /* make sure it is the same expression */
5608 if (!isAstEqual (root->left->left,
5612 if (AST_ULONG_VALUE (root->left->right) != 1)
5615 if (AST_ULONG_VALUE (root->right->right) !=
5616 (getSize (TTYPE (root->left->left)) * 8 - 1))
5619 /* make sure the port supports RLC */
5620 if (port->hasExtBitOp
5621 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5624 /* whew got the first case : create the AST */
5625 return newNode (RLC, root->left->left, NULL);
5629 /* check for second case */
5630 /* (?expr >> 7) | (?expr << 1) */
5631 if (IS_LEFT_OP (root->right) &&
5632 IS_RIGHT_OP (root->left))
5635 if (!SPEC_USIGN (TETYPE (root->left->left)))
5638 if (!IS_AST_LIT_VALUE (root->left->right) ||
5639 !IS_AST_LIT_VALUE (root->right->right))
5642 /* make sure it is the same symbol */
5643 if (!isAstEqual (root->left->left,
5647 if (AST_ULONG_VALUE (root->right->right) != 1)
5650 if (AST_ULONG_VALUE (root->left->right) !=
5651 (getSize (TTYPE (root->left->left)) * 8 - 1))
5654 /* make sure the port supports RLC */
5655 if (port->hasExtBitOp
5656 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5659 /* whew got the first case : create the AST */
5660 return newNode (RLC, root->left->left, NULL);
5665 /* third case for RRC */
5666 /* (?symbol >> 1) | (?symbol << 7) */
5667 if (IS_LEFT_OP (root->right) &&
5668 IS_RIGHT_OP (root->left))
5671 if (!SPEC_USIGN (TETYPE (root->left->left)))
5674 if (!IS_AST_LIT_VALUE (root->left->right) ||
5675 !IS_AST_LIT_VALUE (root->right->right))
5678 /* make sure it is the same symbol */
5679 if (!isAstEqual (root->left->left,
5683 if (AST_ULONG_VALUE (root->left->right) != 1)
5686 if (AST_ULONG_VALUE (root->right->right) !=
5687 (getSize (TTYPE (root->left->left)) * 8 - 1))
5690 /* make sure the port supports RRC */
5691 if (port->hasExtBitOp
5692 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5695 /* whew got the first case : create the AST */
5696 return newNode (RRC, root->left->left, NULL);
5700 /* fourth and last case for now */
5701 /* (?symbol << 7) | (?symbol >> 1) */
5702 if (IS_RIGHT_OP (root->right) &&
5703 IS_LEFT_OP (root->left))
5706 if (!SPEC_USIGN (TETYPE (root->left->left)))
5709 if (!IS_AST_LIT_VALUE (root->left->right) ||
5710 !IS_AST_LIT_VALUE (root->right->right))
5713 /* make sure it is the same symbol */
5714 if (!isAstEqual (root->left->left,
5718 if (AST_ULONG_VALUE (root->right->right) != 1)
5721 if (AST_ULONG_VALUE (root->left->right) !=
5722 (getSize (TTYPE (root->left->left)) * 8 - 1))
5725 /* make sure the port supports RRC */
5726 if (port->hasExtBitOp
5727 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5730 /* whew got the first case : create the AST */
5731 return newNode (RRC, root->left->left, NULL);
5735 /* not found return root */
5739 /*-----------------------------------------------------------------*/
5740 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5741 /*-----------------------------------------------------------------*/
5743 optimizeSWAP (ast * root)
5745 /* will look for trees of the form
5746 (?expr << 4) | (?expr >> 4) or
5747 (?expr >> 4) | (?expr << 4) will make that
5748 into a SWAP : operation ..
5749 note : by 4 I mean (number of bits required to hold the
5751 /* if the root operation is not a | operation then not */
5752 if (!IS_BITOR (root))
5755 /* (?expr << 4) | (?expr >> 4) */
5756 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5757 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5760 if (!SPEC_USIGN (TETYPE (root->left->left)))
5763 if (!IS_AST_LIT_VALUE (root->left->right) ||
5764 !IS_AST_LIT_VALUE (root->right->right))
5767 /* make sure it is the same expression */
5768 if (!isAstEqual (root->left->left,
5772 if (AST_ULONG_VALUE (root->left->right) !=
5773 (getSize (TTYPE (root->left->left)) * 4))
5776 if (AST_ULONG_VALUE (root->right->right) !=
5777 (getSize (TTYPE (root->left->left)) * 4))
5780 /* make sure the port supports SWAP */
5781 if (port->hasExtBitOp
5782 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5785 /* found it : create the AST */
5786 return newNode (SWAP, root->left->left, NULL);
5790 /* not found return root */
5794 /*-----------------------------------------------------------------*/
5795 /* optimizeCompare - optimizes compares for bit variables */
5796 /*-----------------------------------------------------------------*/
5798 optimizeCompare (ast * root)
5800 ast *optExpr = NULL;
5803 unsigned int litValue;
5805 /* if nothing then return nothing */
5809 /* if not a compare op then do leaves */
5810 if (!IS_COMPARE_OP (root))
5812 root->left = optimizeCompare (root->left);
5813 root->right = optimizeCompare (root->right);
5817 /* if left & right are the same then depending
5818 of the operation do */
5819 if (isAstEqual (root->left, root->right))
5821 switch (root->opval.op)
5826 optExpr = newAst_VALUE (constCharVal (0));
5831 optExpr = newAst_VALUE (constCharVal (1));
5835 return decorateType (optExpr, RESULT_TYPE_NONE);
5838 vleft = (root->left->type == EX_VALUE ?
5839 root->left->opval.val : NULL);
5841 vright = (root->right->type == EX_VALUE ?
5842 root->right->opval.val : NULL);
5844 /* if left is a BITVAR in BITSPACE */
5845 /* and right is a LITERAL then */
5846 /* optimize else do nothing */
5847 if (vleft && vright &&
5848 IS_BITVAR (vleft->etype) &&
5849 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5850 IS_LITERAL (vright->etype))
5853 /* if right side > 1 then comparison may never succeed */
5854 if ((litValue = (int) ulFromVal (vright)) > 1)
5856 werror (W_BAD_COMPARE);
5862 switch (root->opval.op)
5864 case '>': /* bit value greater than 1 cannot be */
5865 werror (W_BAD_COMPARE);
5869 case '<': /* bit value < 1 means 0 */
5871 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5874 case LE_OP: /* bit value <= 1 means no check */
5875 optExpr = newAst_VALUE (vright);
5878 case GE_OP: /* bit value >= 1 means only check for = */
5880 optExpr = newAst_VALUE (vleft);
5885 { /* literal is zero */
5886 switch (root->opval.op)
5888 case '<': /* bit value < 0 cannot be */
5889 werror (W_BAD_COMPARE);
5893 case '>': /* bit value > 0 means 1 */
5895 optExpr = newAst_VALUE (vleft);
5898 case LE_OP: /* bit value <= 0 means no check */
5899 case GE_OP: /* bit value >= 0 means no check */
5900 werror (W_BAD_COMPARE);
5904 case EQ_OP: /* bit == 0 means ! of bit */
5905 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5909 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5910 } /* end-of-if of BITVAR */
5916 /*-----------------------------------------------------------------*/
5917 /* addSymToBlock : adds the symbol to the first block we find */
5918 /*-----------------------------------------------------------------*/
5920 addSymToBlock (symbol * sym, ast * tree)
5922 /* reached end of tree or a leaf */
5923 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5927 if (IS_AST_OP (tree) &&
5928 tree->opval.op == BLOCK)
5931 symbol *lsym = copySymbol (sym);
5933 lsym->next = AST_VALUES (tree, sym);
5934 AST_VALUES (tree, sym) = lsym;
5938 addSymToBlock (sym, tree->left);
5939 addSymToBlock (sym, tree->right);
5942 /*-----------------------------------------------------------------*/
5943 /* processRegParms - do processing for register parameters */
5944 /*-----------------------------------------------------------------*/
5946 processRegParms (value * args, ast * body)
5950 if (IS_REGPARM (args->etype))
5951 addSymToBlock (args->sym, body);
5956 /*-----------------------------------------------------------------*/
5957 /* resetParmKey - resets the operandkeys for the symbols */
5958 /*-----------------------------------------------------------------*/
5959 DEFSETFUNC (resetParmKey)
5972 /*------------------------------------------------------------------*/
5973 /* fixupInlineLabel - change a label in an inlined function so that */
5974 /* it is always unique no matter how many times */
5975 /* the function is inlined. */
5976 /*------------------------------------------------------------------*/
5978 fixupInlineLabel (symbol * sym)
5980 char name[SDCC_NAME_MAX + 1];
5982 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5983 strcpy (sym->name, name);
5987 /*------------------------------------------------------------------*/
5988 /* copyAstLoc - copy location information (file, line, block, etc.) */
5989 /* from one ast node to another */
5990 /*------------------------------------------------------------------*/
5992 copyAstLoc (ast * dest, ast * src)
5994 dest->filename = src->filename;
5995 dest->lineno = src->lineno;
5996 dest->level = src->level;
5997 dest->block = src->block;
5998 dest->seqPoint = src->seqPoint;
6003 /*-----------------------------------------------------------------*/
6004 /* fixupInline - perform various fixups on an inline function tree */
6005 /* to take into account that it is no longer a */
6006 /* stand-alone function. */
6007 /*-----------------------------------------------------------------*/
6009 fixupInline (ast * tree, int level)
6011 tree->block = currBlockno;
6013 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6020 /* Add any declared variables back into the symbol table */
6021 decls = tree->values.sym;
6024 decls->level = level;
6025 decls->block = currBlockno;
6026 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6027 decls = decls->next;
6031 tree->level = level;
6033 /* Update symbols */
6034 if (IS_AST_VALUE (tree) &&
6035 tree->opval.val->sym)
6037 symbol * sym = tree->opval.val->sym;
6040 sym->block = currBlockno;
6043 SYM_SPIL_LOC (sym) = NULL;
6046 /* If the symbol is a label, we need to renumber it */
6048 fixupInlineLabel (sym);
6051 /* Update IFX target labels */
6052 if (tree->type == EX_OP && tree->opval.op == IFX)
6054 if (tree->trueLabel)
6055 fixupInlineLabel (tree->trueLabel);
6056 if (tree->falseLabel)
6057 fixupInlineLabel (tree->falseLabel);
6060 /* Replace RETURN with optional assignment and a GOTO to the end */
6061 /* of the inlined function */
6062 if (tree->type == EX_OP && tree->opval.op == RETURN)
6064 ast * assignTree = NULL;
6067 if (inlineState.retsym && tree->right)
6069 assignTree = newNode ('=',
6070 newAst_VALUE (symbolVal (inlineState.retsym)),
6072 copyAstLoc (assignTree, tree);
6075 gotoTree = newNode (GOTO,
6076 newAst_VALUE (symbolVal (inlineState.retlab)),
6078 copyAstLoc (gotoTree, tree);
6080 tree->opval.op = NULLOP;
6081 tree->left = assignTree;
6082 tree->right = gotoTree;
6085 /* Update any children */
6087 fixupInline (tree->left, level);
6089 fixupInline (tree->right, level);
6091 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6093 symbol * label = tree->left->opval.val->sym;
6095 label->key = labelKey++;
6096 /* Add this label back into the symbol table */
6097 addSym (LabelTab, label, label->name, label->level, 0, 0);
6101 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6107 /*-----------------------------------------------------------------*/
6108 /* inlineAddDecl - add a variable declaration to an ast block. It */
6109 /* is also added to the symbol table if addSymTab */
6111 /*-----------------------------------------------------------------*/
6113 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6116 SYM_SPIL_LOC (sym) = NULL;
6120 symbol **decl = &(block->values.sym);
6122 sym->level = block->level;
6123 sym->block = block->block;
6127 if (strcmp ((*decl)->name, sym->name) == 0)
6129 decl = &( (*decl)->next );
6135 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6141 /*-----------------------------------------------------------------*/
6142 /* inlineTempVar - create a temporary variable for inlining */
6143 /*-----------------------------------------------------------------*/
6145 inlineTempVar (sym_link * type, int level)
6149 sym = newSymbol (genSymName(level), level );
6150 sym->type = copyLinkChain (type);
6151 sym->etype = getSpec(sym->type);
6152 SPEC_SCLS (sym->etype) = S_AUTO;
6153 SPEC_OCLS (sym->etype) = NULL;
6154 SPEC_EXTR (sym->etype) = 0;
6155 SPEC_STAT (sym->etype) = 0;
6156 if IS_SPEC (sym->type)
6157 SPEC_VOLATILE (sym->type) = 0;
6159 DCL_PTR_VOLATILE (sym->type) = 0;
6160 SPEC_ABSA (sym->etype) = 0;
6166 /*-----------------------------------------------------------------*/
6167 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6168 /*-----------------------------------------------------------------*/
6170 inlineFindParmRecurse (ast * parms, int *index)
6175 if (parms->type == EX_OP && parms->opval.op == PARAM)
6179 p=inlineFindParmRecurse (parms->left, index);
6182 p=inlineFindParmRecurse (parms->right, index);
6193 /*-----------------------------------------------------------------*/
6194 /* inlineFindParm - search an ast tree of parameters to find one */
6195 /* at a particular index (0=first parameter). */
6196 /* Returns NULL if not found. */
6197 /*-----------------------------------------------------------------*/
6199 inlineFindParm (ast * parms, int index)
6201 return inlineFindParmRecurse (parms, &index);
6204 /*-----------------------------------------------------------------*/
6205 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6206 /*-----------------------------------------------------------------*/
6208 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6215 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6216 if (tempBlockno > maxBlockno)
6217 maxBlockno = tempBlockno;
6219 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6220 if (tempBlockno > maxBlockno)
6221 maxBlockno = tempBlockno;
6223 if (tree->block > maxBlockno)
6224 maxBlockno = tree->block;
6231 /*-----------------------------------------------------------------*/
6232 /* expandInlineFuncs - replace calls to inline functions with the */
6233 /* function itself */
6234 /*-----------------------------------------------------------------*/
6236 expandInlineFuncs (ast * tree, ast * block)
6238 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6239 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6241 symbol * func = tree->left->opval.val->sym;
6244 /* The symbol is probably not bound yet, so find the real one */
6245 csym = findSymWithLevel (SymbolTab, func);
6249 /* Is this an inline function that we can inline? */
6250 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6252 symbol * retsym = NULL;
6260 /* Generate a label for the inlined function to branch to */
6261 /* in case it contains a return statement */
6262 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6265 inlineState.retlab = retlab;
6267 /* Build the subtree for the inlined function in the form: */
6268 /* { //inlinetree block */
6269 /* { //inlinetree2 block */
6270 /* inline_function_code; */
6274 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6275 copyAstLoc (temptree, tree);
6276 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6277 copyAstLoc (temptree, tree);
6278 temptree = newNode (BLOCK, NULL, temptree);
6279 copyAstLoc (temptree, tree);
6280 inlinetree2 = temptree;
6281 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6282 copyAstLoc (inlinetree, tree);
6284 /* To pass parameters to the inlined function, we need some */
6285 /* intermediate variables. This avoids scoping problems */
6286 /* when the parameter declaration names are used differently */
6287 /* during the function call. For example, a function */
6288 /* declared as func(int x, int y) but called as func(y,x). */
6289 /* { //inlinetree block */
6290 /* type1 temparg1; */
6292 /* typen tempargn; */
6293 /* temparg1 = argument1; */
6295 /* tempargn = argumentn; */
6296 /* { //inlinetree2 block */
6300 /* param1 = temparg1; */
6302 /* paramn = tempargn; */
6303 /* inline_function_code; */
6307 args = FUNC_ARGS (func->type);
6314 ast * passedarg = inlineFindParm (tree->right, argIndex);
6318 werror(E_TOO_FEW_PARMS);
6322 temparg = inlineTempVar (args->sym->type, tree->level+1);
6323 inlineAddDecl (temparg, inlinetree, FALSE);
6325 assigntree = newNode ('=',
6326 newAst_VALUE (symbolVal (temparg)),
6328 inlinetree->right = newNode (NULLOP,
6332 parm = copySymbol (args->sym);
6333 inlineAddDecl (parm, inlinetree2, FALSE);
6336 assigntree = newNode ('=',
6337 newAst_VALUE (symbolVal (parm)),
6338 newAst_VALUE (symbolVal (temparg)));
6339 inlinetree2->right = newNode (NULLOP,
6341 inlinetree2->right);
6348 /* Handle the return type */
6349 if (!IS_VOID (func->type->next))
6351 /* Create a temporary symbol to hold the return value and */
6352 /* join it with the inlined function using the comma */
6353 /* operator. The fixupInline function will take care of */
6354 /* changing return statements into assignments to retsym. */
6355 /* (parameter passing and return label omitted for clarity) */
6356 /* rettype retsym; */
6358 /* {{inline_function_code}}, retsym */
6360 retsym = inlineTempVar (func->type->next, tree->level);
6361 inlineAddDecl (retsym, block, TRUE);
6363 tree->opval.op = ',';
6364 tree->left = inlinetree;
6365 tree->right = newAst_VALUE (symbolVal (retsym));
6369 tree->opval.op = NULLOP;
6371 tree->right = inlinetree;
6373 inlineState.retsym = retsym;
6375 /* Renumber the various internal counters on the inlined */
6376 /* function's tree nodes and symbols. Add the inlined */
6377 /* function's local variables to the appropriate scope(s). */
6378 /* Convert inlined return statements to an assignment to */
6379 /* retsym (if needed) and a goto retlab. */
6380 fixupInline (inlinetree, inlinetree->level);
6381 inlineState.count++;
6386 /* Recursively continue to search for functions to inline. */
6387 if (IS_AST_OP (tree))
6389 if (tree->opval.op == BLOCK)
6393 expandInlineFuncs (tree->left, block);
6395 expandInlineFuncs (tree->right, block);
6400 /*-----------------------------------------------------------------*/
6401 /* createFunction - This is the key node that calls the iCode for */
6402 /* generating the code for a function. Note code */
6403 /* is generated function by function, later when */
6404 /* add inter-procedural analysis this will change */
6405 /*-----------------------------------------------------------------*/
6407 createFunction (symbol * name, ast * body)
6413 iCode *piCode = NULL;
6416 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6417 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6419 /* if check function return 0 then some problem */
6420 if (checkFunction (name, NULL) == 0)
6423 /* create a dummy block if none exists */
6425 body = newNode (BLOCK, NULL, NULL);
6429 /* check if the function name already in the symbol table */
6430 if ((csym = findSym (SymbolTab, NULL, name->name)))
6433 /* special case for compiler defined functions
6434 we need to add the name to the publics list : this
6435 actually means we are now compiling the compiler
6439 addSet (&publics, name);
6444 addSymChain (&name);
6445 allocVariables (name);
6447 name->lastLine = lexLineno;
6450 /* set the stack pointer */
6451 stackPtr = -port->stack.direction * port->stack.call_overhead;
6454 if (IFFUNC_ISISR (name->type))
6455 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6457 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6459 if (options.useXstack)
6460 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6462 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6465 fetype = getSpec (name->type); /* get the specifier for the function */
6466 /* if this is a reentrant function then */
6467 if (IFFUNC_ISREENT (name->type))
6470 inlineState.count = 0;
6471 savedBlockno = currBlockno;
6472 currBlockno = inlineFindMaxBlockno (body, 0);
6473 expandInlineFuncs (body, NULL);
6474 currBlockno = savedBlockno;
6476 if (FUNC_ISINLINE (name->type))
6477 name->funcTree = copyAst (body);
6479 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6481 /* do processing for parameters that are passed in registers */
6482 processRegParms (FUNC_ARGS(name->type), body);
6484 /* set the stack pointer */
6488 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6490 /* allocate & autoinit the block variables */
6491 processBlockVars (body, &stack, ALLOCATE);
6493 /* name needs to be mangled */
6494 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6496 body = resolveSymbols (body); /* resolve the symbols */
6497 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6499 /* save the stack information */
6500 if (options.useXstack)
6501 name->xstack = SPEC_STAK (fetype) = stack;
6503 name->stack = SPEC_STAK (fetype) = stack;
6505 ex = newAst_VALUE (symbolVal (name)); /* create name */
6506 ex = newNode (FUNCTION, ex, body);
6507 ex->values.args = FUNC_ARGS(name->type);
6509 if (options.dump_tree)
6514 /* Do not generate code for inline functions unless extern also. */
6516 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6519 /* Temporary hack: always generate code for static inline functions. */
6520 /* Ideally static inline functions should only be generated if needed. */
6521 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6525 /* create the node & generate intermediate code */
6527 codeOutBuf = &code->oBuf;
6528 piCode = iCodeFromAst (ex);
6529 name->generated = 1;
6534 eBBlockFromiCode (piCode);
6536 /* if there are any statics then do them */
6539 GcurMemmap = statsg;
6540 codeOutBuf = &statsg->oBuf;
6541 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6547 /* dealloc the block variables */
6548 processBlockVars (body, &stack, DEALLOCATE);
6549 outputDebugStackSymbols();
6550 /* deallocate paramaters */
6551 deallocParms (FUNC_ARGS(name->type));
6553 if (IFFUNC_ISREENT (name->type))
6556 /* we are done freeup memory & cleanup */
6558 if (port->reset_labelKey) labelKey = 1;
6560 FUNC_HASBODY(name->type) = 1;
6561 addSet (&operKeyReset, name);
6562 applyToSet (operKeyReset, resetParmKey);
6567 cleanUpLevel (LabelTab, 0);
6568 cleanUpBlock (StructTab, 1);
6569 cleanUpBlock (TypedefTab, 1);
6571 xstack->syms = NULL;
6572 istack->syms = NULL;
6577 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6578 /*-----------------------------------------------------------------*/
6579 /* ast_print : prints the ast (for debugging purposes) */
6580 /*-----------------------------------------------------------------*/
6582 void ast_print (ast * tree, FILE *outfile, int indent)
6587 /* can print only decorated trees */
6588 if (!tree->decorated) return;
6590 /* if any child is an error | this one is an error do nothing */
6591 if (tree->isError ||
6592 (tree->left && tree->left->isError) ||
6593 (tree->right && tree->right->isError)) {
6594 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6598 /* print the line */
6599 /* if not block & function */
6600 if (tree->type == EX_OP &&
6601 (tree->opval.op != FUNCTION &&
6602 tree->opval.op != BLOCK &&
6603 tree->opval.op != NULLOP)) {
6606 if (tree->opval.op == FUNCTION) {
6608 value *args=FUNC_ARGS(tree->left->opval.val->type);
6609 fprintf(outfile,"FUNCTION (%s=%p) type (",
6610 tree->left->opval.val->name, tree);
6611 printTypeChain (tree->left->opval.val->type->next,outfile);
6612 fprintf(outfile,") args (");
6615 fprintf (outfile, ", ");
6617 printTypeChain (args ? args->type : NULL, outfile);
6619 args= args ? args->next : NULL;
6621 fprintf(outfile,")\n");
6622 ast_print(tree->left,outfile,indent);
6623 ast_print(tree->right,outfile,indent);
6626 if (tree->opval.op == BLOCK) {
6627 symbol *decls = tree->values.sym;
6628 INDENT(indent,outfile);
6629 fprintf(outfile,"{\n");
6631 INDENT(indent+2,outfile);
6632 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6633 decls->name, decls);
6634 printTypeChain(decls->type,outfile);
6635 fprintf(outfile,")\n");
6637 decls = decls->next;
6639 ast_print(tree->right,outfile,indent+2);
6640 INDENT(indent,outfile);
6641 fprintf(outfile,"}\n");
6644 if (tree->opval.op == NULLOP) {
6645 ast_print(tree->left,outfile,indent);
6646 ast_print(tree->right,outfile,indent);
6649 INDENT(indent,outfile);
6651 /*------------------------------------------------------------------*/
6652 /*----------------------------*/
6653 /* leaf has been reached */
6654 /*----------------------------*/
6655 /* if this is of type value */
6656 /* just get the type */
6657 if (tree->type == EX_VALUE) {
6659 if (IS_LITERAL (tree->opval.val->etype)) {
6660 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6661 if (SPEC_USIGN (tree->opval.val->etype))
6662 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6664 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6665 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6666 floatFromVal(tree->opval.val));
6667 } else if (tree->opval.val->sym) {
6668 /* if the undefined flag is set then give error message */
6669 if (tree->opval.val->sym->undefined) {
6670 fprintf(outfile,"UNDEFINED SYMBOL ");
6672 fprintf(outfile,"SYMBOL ");
6674 fprintf(outfile,"(%s=%p @ %p)",
6675 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6678 fprintf(outfile," type (");
6679 printTypeChain(tree->ftype,outfile);
6680 fprintf(outfile,")\n");
6682 fprintf(outfile,"\n");
6687 /* if type link for the case of cast */
6688 if (tree->type == EX_LINK) {
6689 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6690 printTypeChain(tree->opval.lnk,outfile);
6691 fprintf(outfile,")\n");
6696 /* depending on type of operator do */
6698 switch (tree->opval.op) {
6699 /*------------------------------------------------------------------*/
6700 /*----------------------------*/
6702 /*----------------------------*/
6704 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6705 printTypeChain(tree->ftype,outfile);
6706 fprintf(outfile,")\n");
6707 ast_print(tree->left,outfile,indent+2);
6708 ast_print(tree->right,outfile,indent+2);
6711 /*------------------------------------------------------------------*/
6712 /*----------------------------*/
6714 /*----------------------------*/
6716 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6717 printTypeChain(tree->ftype,outfile);
6718 fprintf(outfile,")\n");
6719 ast_print(tree->left,outfile,indent+2);
6720 ast_print(tree->right,outfile,indent+2);
6723 /*------------------------------------------------------------------*/
6724 /*----------------------------*/
6725 /* struct/union pointer */
6726 /*----------------------------*/
6728 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6729 printTypeChain(tree->ftype,outfile);
6730 fprintf(outfile,")\n");
6731 ast_print(tree->left,outfile,indent+2);
6732 ast_print(tree->right,outfile,indent+2);
6735 /*------------------------------------------------------------------*/
6736 /*----------------------------*/
6737 /* ++/-- operation */
6738 /*----------------------------*/
6741 fprintf(outfile,"post-");
6743 fprintf(outfile,"pre-");
6744 fprintf(outfile,"INC_OP (%p) type (",tree);
6745 printTypeChain(tree->ftype,outfile);
6746 fprintf(outfile,")\n");
6747 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6748 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6753 fprintf(outfile,"post-");
6755 fprintf(outfile,"pre-");
6756 fprintf(outfile,"DEC_OP (%p) type (",tree);
6757 printTypeChain(tree->ftype,outfile);
6758 fprintf(outfile,")\n");
6759 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6760 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6763 /*------------------------------------------------------------------*/
6764 /*----------------------------*/
6766 /*----------------------------*/
6769 fprintf(outfile,"& (%p) type (",tree);
6770 printTypeChain(tree->ftype,outfile);
6771 fprintf(outfile,")\n");
6772 ast_print(tree->left,outfile,indent+2);
6773 ast_print(tree->right,outfile,indent+2);
6775 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6776 printTypeChain(tree->ftype,outfile);
6777 fprintf(outfile,")\n");
6778 ast_print(tree->left,outfile,indent+2);
6779 ast_print(tree->right,outfile,indent+2);
6782 /*----------------------------*/
6784 /*----------------------------*/
6786 fprintf(outfile,"OR (%p) type (",tree);
6787 printTypeChain(tree->ftype,outfile);
6788 fprintf(outfile,")\n");
6789 ast_print(tree->left,outfile,indent+2);
6790 ast_print(tree->right,outfile,indent+2);
6792 /*------------------------------------------------------------------*/
6793 /*----------------------------*/
6795 /*----------------------------*/
6797 fprintf(outfile,"XOR (%p) type (",tree);
6798 printTypeChain(tree->ftype,outfile);
6799 fprintf(outfile,")\n");
6800 ast_print(tree->left,outfile,indent+2);
6801 ast_print(tree->right,outfile,indent+2);
6804 /*------------------------------------------------------------------*/
6805 /*----------------------------*/
6807 /*----------------------------*/
6809 fprintf(outfile,"DIV (%p) type (",tree);
6810 printTypeChain(tree->ftype,outfile);
6811 fprintf(outfile,")\n");
6812 ast_print(tree->left,outfile,indent+2);
6813 ast_print(tree->right,outfile,indent+2);
6815 /*------------------------------------------------------------------*/
6816 /*----------------------------*/
6818 /*----------------------------*/
6820 fprintf(outfile,"MOD (%p) type (",tree);
6821 printTypeChain(tree->ftype,outfile);
6822 fprintf(outfile,")\n");
6823 ast_print(tree->left,outfile,indent+2);
6824 ast_print(tree->right,outfile,indent+2);
6827 /*------------------------------------------------------------------*/
6828 /*----------------------------*/
6829 /* address dereference */
6830 /*----------------------------*/
6831 case '*': /* can be unary : if right is null then unary operation */
6833 fprintf(outfile,"DEREF (%p) type (",tree);
6834 printTypeChain(tree->ftype,outfile);
6835 fprintf(outfile,")\n");
6836 ast_print(tree->left,outfile,indent+2);
6839 /*------------------------------------------------------------------*/
6840 /*----------------------------*/
6841 /* multiplication */
6842 /*----------------------------*/
6843 fprintf(outfile,"MULT (%p) type (",tree);
6844 printTypeChain(tree->ftype,outfile);
6845 fprintf(outfile,")\n");
6846 ast_print(tree->left,outfile,indent+2);
6847 ast_print(tree->right,outfile,indent+2);
6851 /*------------------------------------------------------------------*/
6852 /*----------------------------*/
6853 /* unary '+' operator */
6854 /*----------------------------*/
6858 fprintf(outfile,"UPLUS (%p) type (",tree);
6859 printTypeChain(tree->ftype,outfile);
6860 fprintf(outfile,")\n");
6861 ast_print(tree->left,outfile,indent+2);
6863 /*------------------------------------------------------------------*/
6864 /*----------------------------*/
6866 /*----------------------------*/
6867 fprintf(outfile,"ADD (%p) type (",tree);
6868 printTypeChain(tree->ftype,outfile);
6869 fprintf(outfile,")\n");
6870 ast_print(tree->left,outfile,indent+2);
6871 ast_print(tree->right,outfile,indent+2);
6874 /*------------------------------------------------------------------*/
6875 /*----------------------------*/
6877 /*----------------------------*/
6878 case '-': /* can be unary */
6880 fprintf(outfile,"UMINUS (%p) type (",tree);
6881 printTypeChain(tree->ftype,outfile);
6882 fprintf(outfile,")\n");
6883 ast_print(tree->left,outfile,indent+2);
6885 /*------------------------------------------------------------------*/
6886 /*----------------------------*/
6888 /*----------------------------*/
6889 fprintf(outfile,"SUB (%p) type (",tree);
6890 printTypeChain(tree->ftype,outfile);
6891 fprintf(outfile,")\n");
6892 ast_print(tree->left,outfile,indent+2);
6893 ast_print(tree->right,outfile,indent+2);
6896 /*------------------------------------------------------------------*/
6897 /*----------------------------*/
6899 /*----------------------------*/
6901 fprintf(outfile,"COMPL (%p) type (",tree);
6902 printTypeChain(tree->ftype,outfile);
6903 fprintf(outfile,")\n");
6904 ast_print(tree->left,outfile,indent+2);
6906 /*------------------------------------------------------------------*/
6907 /*----------------------------*/
6909 /*----------------------------*/
6911 fprintf(outfile,"NOT (%p) type (",tree);
6912 printTypeChain(tree->ftype,outfile);
6913 fprintf(outfile,")\n");
6914 ast_print(tree->left,outfile,indent+2);
6916 /*------------------------------------------------------------------*/
6917 /*----------------------------*/
6919 /*----------------------------*/
6921 fprintf(outfile,"RRC (%p) type (",tree);
6922 printTypeChain(tree->ftype,outfile);
6923 fprintf(outfile,")\n");
6924 ast_print(tree->left,outfile,indent+2);
6928 fprintf(outfile,"RLC (%p) type (",tree);
6929 printTypeChain(tree->ftype,outfile);
6930 fprintf(outfile,")\n");
6931 ast_print(tree->left,outfile,indent+2);
6934 fprintf(outfile,"SWAP (%p) type (",tree);
6935 printTypeChain(tree->ftype,outfile);
6936 fprintf(outfile,")\n");
6937 ast_print(tree->left,outfile,indent+2);
6940 fprintf(outfile,"GETHBIT (%p) type (",tree);
6941 printTypeChain(tree->ftype,outfile);
6942 fprintf(outfile,")\n");
6943 ast_print(tree->left,outfile,indent+2);
6946 fprintf(outfile,"GETABIT (%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,"GETBYTE (%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,"GETWORD (%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,"LEFT_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);
6974 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6975 printTypeChain(tree->ftype,outfile);
6976 fprintf(outfile,")\n");
6977 ast_print(tree->left,outfile,indent+2);
6978 ast_print(tree->right,outfile,indent+2);
6980 /*------------------------------------------------------------------*/
6981 /*----------------------------*/
6983 /*----------------------------*/
6984 case CAST: /* change the type */
6985 fprintf(outfile,"CAST (%p) from type (",tree);
6986 printTypeChain(tree->right->ftype,outfile);
6987 fprintf(outfile,") to type (");
6988 printTypeChain(tree->ftype,outfile);
6989 fprintf(outfile,")\n");
6990 ast_print(tree->right,outfile,indent+2);
6994 fprintf(outfile,"ANDAND (%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 fprintf(outfile,"OROR (%p) type (",tree);
7002 printTypeChain(tree->ftype,outfile);
7003 fprintf(outfile,")\n");
7004 ast_print(tree->left,outfile,indent+2);
7005 ast_print(tree->right,outfile,indent+2);
7008 /*------------------------------------------------------------------*/
7009 /*----------------------------*/
7010 /* comparison operators */
7011 /*----------------------------*/
7013 fprintf(outfile,"GT(>) (%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,"LT(<) (%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,"LE(<=) (%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,"GE(>=) (%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,"EQ(==) (%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);
7048 fprintf(outfile,"NE(!=) (%p) type (",tree);
7049 printTypeChain(tree->ftype,outfile);
7050 fprintf(outfile,")\n");
7051 ast_print(tree->left,outfile,indent+2);
7052 ast_print(tree->right,outfile,indent+2);
7053 /*------------------------------------------------------------------*/
7054 /*----------------------------*/
7056 /*----------------------------*/
7057 case SIZEOF: /* evaluate wihout code generation */
7058 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7061 /*------------------------------------------------------------------*/
7062 /*----------------------------*/
7063 /* conditional operator '?' */
7064 /*----------------------------*/
7066 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7067 printTypeChain(tree->ftype,outfile);
7068 fprintf(outfile,")\n");
7069 ast_print(tree->left,outfile,indent+2);
7070 ast_print(tree->right,outfile,indent+2);
7074 fprintf(outfile,"COLON(:) (%p) type (",tree);
7075 printTypeChain(tree->ftype,outfile);
7076 fprintf(outfile,")\n");
7077 ast_print(tree->left,outfile,indent+2);
7078 ast_print(tree->right,outfile,indent+2);
7081 /*------------------------------------------------------------------*/
7082 /*----------------------------*/
7083 /* assignment operators */
7084 /*----------------------------*/
7086 fprintf(outfile,"MULASS(*=) (%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,"DIVASS(/=) (%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,"ANDASS(&=) (%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,"ORASS(|=) (%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,"XORASS(^=) (%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,"RSHFTASS(>>=) (%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);
7128 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7129 printTypeChain(tree->ftype,outfile);
7130 fprintf(outfile,")\n");
7131 ast_print(tree->left,outfile,indent+2);
7132 ast_print(tree->right,outfile,indent+2);
7134 /*------------------------------------------------------------------*/
7135 /*----------------------------*/
7137 /*----------------------------*/
7139 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7140 printTypeChain(tree->ftype,outfile);
7141 fprintf(outfile,")\n");
7142 ast_print(tree->left,outfile,indent+2);
7143 ast_print(tree->right,outfile,indent+2);
7145 /*------------------------------------------------------------------*/
7146 /*----------------------------*/
7148 /*----------------------------*/
7150 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7151 printTypeChain(tree->ftype,outfile);
7152 fprintf(outfile,")\n");
7153 ast_print(tree->left,outfile,indent+2);
7154 ast_print(tree->right,outfile,indent+2);
7156 /*------------------------------------------------------------------*/
7157 /*----------------------------*/
7158 /* straight assignemnt */
7159 /*----------------------------*/
7161 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7162 printTypeChain(tree->ftype,outfile);
7163 fprintf(outfile,")\n");
7164 ast_print(tree->left,outfile,indent+2);
7165 ast_print(tree->right,outfile,indent+2);
7167 /*------------------------------------------------------------------*/
7168 /*----------------------------*/
7169 /* comma operator */
7170 /*----------------------------*/
7172 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7173 printTypeChain(tree->ftype,outfile);
7174 fprintf(outfile,")\n");
7175 ast_print(tree->left,outfile,indent+2);
7176 ast_print(tree->right,outfile,indent+2);
7178 /*------------------------------------------------------------------*/
7179 /*----------------------------*/
7181 /*----------------------------*/
7184 fprintf(outfile,"CALL (%p) type (",tree);
7185 printTypeChain(tree->ftype,outfile);
7186 fprintf(outfile,")\n");
7187 ast_print(tree->left,outfile,indent+2);
7188 ast_print(tree->right,outfile,indent+2);
7191 fprintf(outfile,"PARMS\n");
7192 ast_print(tree->left,outfile,indent+2);
7193 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7194 ast_print(tree->right,outfile,indent+2);
7197 /*------------------------------------------------------------------*/
7198 /*----------------------------*/
7199 /* return statement */
7200 /*----------------------------*/
7202 fprintf(outfile,"RETURN (%p) type (",tree);
7204 printTypeChain(tree->right->ftype,outfile);
7206 fprintf(outfile,")\n");
7207 ast_print(tree->right,outfile,indent+2);
7209 /*------------------------------------------------------------------*/
7210 /*----------------------------*/
7211 /* label statement */
7212 /*----------------------------*/
7214 fprintf(outfile,"LABEL (%p)\n",tree);
7215 ast_print(tree->left,outfile,indent+2);
7216 ast_print(tree->right,outfile,indent);
7218 /*------------------------------------------------------------------*/
7219 /*----------------------------*/
7220 /* switch statement */
7221 /*----------------------------*/
7225 fprintf(outfile,"SWITCH (%p) ",tree);
7226 ast_print(tree->left,outfile,0);
7227 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7228 INDENT(indent+2,outfile);
7229 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7230 (int) ulFromVal(val),
7231 tree->values.switchVals.swNum,
7232 (int) ulFromVal(val));
7234 ast_print(tree->right,outfile,indent);
7237 /*------------------------------------------------------------------*/
7238 /*----------------------------*/
7240 /*----------------------------*/
7242 fprintf(outfile,"IF (%p) \n",tree);
7243 ast_print(tree->left,outfile,indent+2);
7244 if (tree->trueLabel) {
7245 INDENT(indent+2,outfile);
7246 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7248 if (tree->falseLabel) {
7249 INDENT(indent+2,outfile);
7250 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7252 ast_print(tree->right,outfile,indent+2);
7254 /*----------------------------*/
7255 /* goto Statement */
7256 /*----------------------------*/
7258 fprintf(outfile,"GOTO (%p) \n",tree);
7259 ast_print(tree->left,outfile,indent+2);
7260 fprintf(outfile,"\n");
7262 /*------------------------------------------------------------------*/
7263 /*----------------------------*/
7265 /*----------------------------*/
7267 fprintf(outfile,"FOR (%p) \n",tree);
7268 if (AST_FOR( tree, initExpr)) {
7269 INDENT(indent+2,outfile);
7270 fprintf(outfile,"INIT EXPR ");
7271 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7273 if (AST_FOR( tree, condExpr)) {
7274 INDENT(indent+2,outfile);
7275 fprintf(outfile,"COND EXPR ");
7276 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7278 if (AST_FOR( tree, loopExpr)) {
7279 INDENT(indent+2,outfile);
7280 fprintf(outfile,"LOOP EXPR ");
7281 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7283 fprintf(outfile,"FOR LOOP BODY \n");
7284 ast_print(tree->left,outfile,indent+2);
7287 fprintf(outfile,"CRITICAL (%p) \n",tree);
7288 ast_print(tree->left,outfile,indent+2);
7296 ast_print(t,stdout,0);
7299 /*-----------------------------------------------------------------*/
7300 /* astErrors : returns non-zero if errors present in tree */
7301 /*-----------------------------------------------------------------*/
7302 int astErrors(ast *t)
7311 if (t->type == EX_VALUE
7312 && t->opval.val->sym
7313 && t->opval.val->sym->undefined)
7316 errors += astErrors(t->left);
7317 errors += astErrors(t->right);