1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
546 /* if this is a label resolve it from the labelTab */
547 if (IS_AST_VALUE (tree) &&
548 tree->opval.val->sym &&
549 tree->opval.val->sym->islbl)
552 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
553 tree->opval.val->sym->name);
556 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
557 tree->opval.val->sym->name);
559 tree->opval.val->sym = csym;
561 goto resolveChildren;
564 /* do only for leafs */
565 if (IS_AST_VALUE (tree) &&
566 tree->opval.val->sym &&
567 !tree->opval.val->sym->implicit)
570 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
572 /* if found in the symbol table & they are not the same */
573 if (csym && tree->opval.val->sym != csym)
575 tree->opval.val->sym = csym;
576 tree->opval.val->type = csym->type;
577 tree->opval.val->etype = csym->etype;
580 /* if not found in the symbol table */
581 /* mark it as undefined & assume it */
582 /* is an integer in data space */
583 if (!csym && !tree->opval.val->sym->implicit)
586 /* if this is a function name then */
587 /* mark it as returning an int */
590 tree->opval.val->sym->type = newLink (DECLARATOR);
591 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
592 tree->opval.val->sym->type->next =
593 tree->opval.val->sym->etype = newIntLink ();
594 tree->opval.val->etype = tree->opval.val->etype;
595 tree->opval.val->type = tree->opval.val->sym->type;
596 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
597 tree->opval.val->sym->name);
598 //tree->opval.val->sym->undefined = 1;
599 allocVariables (tree->opval.val->sym);
603 tree->opval.val->sym->undefined = 1;
604 tree->opval.val->type =
605 tree->opval.val->etype = newIntLink ();
606 tree->opval.val->sym->type =
607 tree->opval.val->sym->etype = newIntLink ();
613 resolveSymbols (tree->left);
614 resolveSymbols (tree->right);
619 /*------------------------------------------------------------------------*/
620 /* setAstFileLine - walks a ast tree & sets the file name and line number */
621 /*------------------------------------------------------------------------*/
622 int setAstFileLine (ast * tree, char *filename, int lineno)
627 tree->filename = filename;
628 tree->lineno = lineno;
629 setAstFileLine (tree->left, filename, lineno);
630 setAstFileLine (tree->right, filename, lineno);
634 /*-----------------------------------------------------------------*/
635 /* funcOfType :- function of type with name */
636 /*-----------------------------------------------------------------*/
638 funcOfType (char *name, sym_link * type, sym_link * argType,
642 /* create the symbol */
643 sym = newSymbol (name, 0);
645 /* setup return value */
646 sym->type = newLink (DECLARATOR);
647 DCL_TYPE (sym->type) = FUNCTION;
648 sym->type->next = copyLinkChain (type);
649 sym->etype = getSpec (sym->type);
650 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
652 /* if arguments required */
656 args = FUNC_ARGS(sym->type) = newValue ();
660 args->type = copyLinkChain (argType);
661 args->etype = getSpec (args->type);
662 SPEC_EXTR(args->etype)=1;
665 args = args->next = newValue ();
672 allocVariables (sym);
677 /*-----------------------------------------------------------------*/
678 /* funcOfTypeVarg :- function of type with name and argtype */
679 /*-----------------------------------------------------------------*/
681 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
686 /* create the symbol */
687 sym = newSymbol (name, 0);
689 /* setup return value */
690 sym->type = newLink (DECLARATOR);
691 DCL_TYPE (sym->type) = FUNCTION;
692 sym->type->next = typeFromStr(rtype);
693 sym->etype = getSpec (sym->type);
695 /* if arguments required */
698 args = FUNC_ARGS(sym->type) = newValue ();
700 for ( i = 0 ; i < nArgs ; i++ ) {
701 args->type = typeFromStr(atypes[i]);
702 args->etype = getSpec (args->type);
703 SPEC_EXTR(args->etype)=1;
704 if ((i + 1) == nArgs) break;
705 args = args->next = newValue ();
712 allocVariables (sym);
717 /*-----------------------------------------------------------------*/
718 /* reverseParms - will reverse a parameter tree */
719 /*-----------------------------------------------------------------*/
721 reverseParms (ast * ptree)
727 /* top down if we find a nonParm tree then quit */
728 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
730 /* The various functions expect the parameter tree to be right heavy. */
731 /* Rotate the tree to be left heavy so that after reversal it is */
732 /* right heavy again. */
733 while ((ttree = ptree->right) && ttree->type == EX_OP &&
734 ttree->opval.op == PARAM)
736 ptree->right = ttree->right;
737 ttree->right = ttree->left;
738 ttree->left = ptree->left;
744 ptree->left = ptree->right;
745 ptree->right = ttree;
747 reverseParms (ptree->left);
748 reverseParms (ptree->right);
754 /*-----------------------------------------------------------------*/
755 /* processParms - makes sure the parameters are okay and do some */
756 /* processing with them */
757 /*-----------------------------------------------------------------*/
759 processParms (ast *func,
762 int *parmNumber, /* unused, although updated */
765 RESULT_TYPE resultType;
768 /* if none of them exist */
769 if (!defParm && !*actParm)
774 if (getenv("DEBUG_SANITY"))
776 fprintf (stderr, "processParms: %s ", defParm->name);
778 /* make sure the type is complete and sane */
779 checkTypeSanity(defParm->etype, defParm->name);
782 if (IS_CODEPTR (func->ftype))
783 functype = func->ftype->next;
785 functype = func->ftype;
787 /* if the function is being called via a pointer & */
788 /* it has not been defined reentrant then we cannot */
789 /* have parameters */
790 /* PIC16 port can... */
791 if (!TARGET_IS_PIC16)
793 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
795 werror (E_NONRENT_ARGS);
801 /* if defined parameters ended but actual parameters */
802 /* exist and this is not defined as a variable arg */
803 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
805 werror (E_TOO_MANY_PARMS);
809 /* if defined parameters present but no actual parameters */
810 if (defParm && !*actParm)
812 werror (E_TOO_FEW_PARMS);
816 /* if this is a PARAM node then match left & right */
817 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
819 (*actParm)->decorated = 1;
820 return (processParms (func, defParm,
821 &(*actParm)->left, parmNumber, FALSE) ||
822 processParms (func, defParm ? defParm->next : NULL,
823 &(*actParm)->right, parmNumber, rightmost));
825 else if (defParm) /* not vararg */
827 /* If we have found a value node by following only right-hand links,
828 * then we know that there are no more values after us.
830 * Therefore, if there are more defined parameters, the caller didn't
833 if (rightmost && defParm->next)
835 werror (E_TOO_FEW_PARMS);
840 /* decorate parameter */
841 resultType = defParm ? getResultTypeFromType (defParm->type) :
843 *actParm = decorateType (*actParm, resultType);
845 if (IS_VOID((*actParm)->ftype))
847 werror (E_VOID_VALUE_USED);
851 /* If this is a varargs function... */
852 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
857 if (IS_CAST_OP (*actParm) ||
858 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
859 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast)))
861 /* Parameter was explicitly typecast; don't touch it. */
865 ftype = (*actParm)->ftype;
867 /* If it's a char, upcast to int. */
868 if (IS_INTEGRAL (ftype)
869 && (getSize (ftype) < (unsigned) INTSIZE))
871 newType = newAst_LINK(INTTYPE);
874 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
876 newType = newAst_LINK (copyLinkChain(ftype));
877 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
880 if (IS_AGGREGATE (ftype))
882 newType = newAst_LINK (copyLinkChain (ftype));
883 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
888 /* cast required; change this op to a cast. */
889 (*actParm)->decorated = 0;
890 *actParm = newNode (CAST, newType, *actParm);
891 (*actParm)->filename = (*actParm)->right->filename;
892 (*actParm)->lineno = (*actParm)->right->lineno;
894 decorateType (*actParm, RESULT_TYPE_NONE);
899 /* if defined parameters ended but actual has not & */
901 if (!defParm && *actParm &&
902 (options.stackAuto || IFFUNC_ISREENT (functype)))
905 resolveSymbols (*actParm);
907 /* the parameter type must be at least castable */
908 if (compareType (defParm->type, (*actParm)->ftype) == 0)
910 werror (E_INCOMPAT_TYPES);
911 printFromToType ((*actParm)->ftype, defParm->type);
915 /* if the parameter is castable then add the cast */
916 if (compareType (defParm->type, (*actParm)->ftype) < 0)
920 resultType = getResultTypeFromType (defParm->etype);
921 pTree = resolveSymbols (copyAst (*actParm));
923 /* now change the current one to a cast */
924 (*actParm)->type = EX_OP;
925 (*actParm)->opval.op = CAST;
926 (*actParm)->left = newAst_LINK (defParm->type);
927 (*actParm)->right = pTree;
928 (*actParm)->decorated = 0; /* force typechecking */
929 decorateType (*actParm, resultType);
932 /* make a copy and change the regparm type to the defined parm */
933 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
934 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
935 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
937 /* if the function is being called via a pointer & */
938 /* this parameter is not passed in registers */
939 /* then the function must be defined reentrant */
940 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
941 !IFFUNC_ISREENT (functype) && !options.stackAuto)
943 werror (E_NONRENT_ARGS);
952 /*-----------------------------------------------------------------*/
953 /* createIvalType - generates ival for basic types */
954 /*-----------------------------------------------------------------*/
956 createIvalType (ast * sym, sym_link * type, initList * ilist)
960 /* if initList is deep */
961 if (ilist->type == INIT_DEEP)
962 ilist = ilist->init.deep;
964 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
965 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
968 /*-----------------------------------------------------------------*/
969 /* createIvalStruct - generates initial value for structures */
970 /*-----------------------------------------------------------------*/
972 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
979 sflds = SPEC_STRUCT (type)->fields;
980 if (ilist->type != INIT_DEEP)
982 werror (E_INIT_STRUCT, "");
986 iloop = ilist->init.deep;
988 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
990 /* if we have come to end */
994 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
995 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
996 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
997 iloop, rast, rootValue)),
1004 if (IS_AST_VALUE (sym))
1005 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1006 W_EXCESS_INITIALIZERS, "struct",
1007 sym->opval.val->sym->name);
1009 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1016 /*-----------------------------------------------------------------*/
1017 /* createIvalArray - generates code for array initialization */
1018 /*-----------------------------------------------------------------*/
1020 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1024 int lcnt = 0, size = 0;
1025 literalList *literalL;
1027 /* take care of the special case */
1028 /* array of characters can be init */
1030 if (IS_CHAR (type->next))
1031 if ((rast = createIvalCharPtr (sym,
1033 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1036 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1038 /* not the special case */
1039 if (ilist->type != INIT_DEEP)
1041 werror (E_INIT_STRUCT, "");
1045 iloop = ilist->init.deep;
1046 lcnt = DCL_ELEM (type);
1048 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1052 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1054 rast = newNode(ARRAYINIT, aSym, NULL);
1055 rast->values.constlist = literalL;
1057 // Make sure size is set to length of initializer list.
1061 iloop = iloop->next;
1064 if (lcnt && size > lcnt)
1066 // Array size was specified, and we have more initializers than needed.
1067 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1068 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1077 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1078 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1079 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1080 iloop = (iloop ? iloop->next : NULL);
1086 /* no of elements given and we */
1087 /* have generated for all of them */
1090 // is this a better way? at least it won't crash
1091 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1092 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1099 /* if we have not been given a size */
1100 if (!DCL_ELEM (type))
1102 /* check, if it's a flexible array */
1103 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1104 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1106 DCL_ELEM (type) = size;
1109 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1113 /*-----------------------------------------------------------------*/
1114 /* createIvalCharPtr - generates initial values for char pointers */
1115 /*-----------------------------------------------------------------*/
1117 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1122 /* if this is a pointer & right is a literal array then */
1123 /* just assignment will do */
1124 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1125 SPEC_SCLS (iexpr->etype) == S_CODE)
1126 && IS_ARRAY (iexpr->ftype)))
1127 return newNode ('=', sym, iexpr);
1129 /* left side is an array so we have to assign each element */
1130 if ((IS_LITERAL (iexpr->etype) ||
1131 SPEC_SCLS (iexpr->etype) == S_CODE)
1132 && IS_ARRAY (iexpr->ftype))
1134 /* for each character generate an assignment */
1135 /* to the array element */
1136 char *s = SPEC_CVAL (iexpr->etype).v_char;
1138 unsigned int symsize = getSize (type);
1140 size = getSize (iexpr->ftype);
1141 if (symsize && size>symsize)
1143 if (size>(symsize+1))
1145 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1147 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1153 for (i=0;i<size;i++)
1155 rast = newNode (NULLOP,
1159 newAst_VALUE (valueFromLit ((float) i))),
1160 newAst_VALUE (valueFromLit (*s))));
1164 // now WE don't need iexpr's symbol anymore
1165 freeStringSymbol(AST_SYMBOL(iexpr));
1167 /* if we have not been given a size */
1168 if (!DCL_ELEM (type))
1170 /* check, if it's a flexible array */
1171 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1172 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1174 DCL_ELEM (type) = size;
1177 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1183 /*-----------------------------------------------------------------*/
1184 /* createIvalPtr - generates initial value for pointers */
1185 /*-----------------------------------------------------------------*/
1187 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1193 if (ilist->type == INIT_DEEP)
1194 ilist = ilist->init.deep;
1196 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1198 /* if character pointer */
1199 if (IS_CHAR (type->next))
1200 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1203 return newNode ('=', sym, iexpr);
1206 /*-----------------------------------------------------------------*/
1207 /* createIval - generates code for initial value */
1208 /*-----------------------------------------------------------------*/
1210 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1217 /* if structure then */
1218 if (IS_STRUCT (type))
1219 rast = createIvalStruct (sym, type, ilist, rootValue);
1221 /* if this is a pointer */
1223 rast = createIvalPtr (sym, type, ilist, rootValue);
1225 /* if this is an array */
1226 if (IS_ARRAY (type))
1227 rast = createIvalArray (sym, type, ilist, rootValue);
1229 /* if type is SPECIFIER */
1231 rast = createIvalType (sym, type, ilist);
1234 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1236 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1239 /*-----------------------------------------------------------------*/
1240 /* initAggregates - initialises aggregate variables with initv */
1241 /*-----------------------------------------------------------------*/
1242 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1243 ast *newAst = newAst_VALUE (symbolVal (sym));
1244 return createIval (newAst, sym->type, ival, wid, newAst);
1247 /*-----------------------------------------------------------------*/
1248 /* gatherAutoInit - creates assignment expressions for initial */
1250 /*-----------------------------------------------------------------*/
1252 gatherAutoInit (symbol * autoChain)
1259 for (sym = autoChain; sym; sym = sym->next)
1262 /* resolve the symbols in the ival */
1264 resolveIvalSym (sym->ival, sym->type);
1267 /* if we are PIC16 port,
1268 * and this is a static,
1269 * and have initial value,
1270 * and not S_CODE, don't emit in gs segment,
1271 * but allow glue.c:pic16emitRegularMap to put symbol
1272 * in idata section */
1273 if(TARGET_IS_PIC16 &&
1274 IS_STATIC (sym->etype) && sym->ival
1275 && SPEC_SCLS(sym->etype) != S_CODE) {
1276 SPEC_SCLS (sym->etype) = S_DATA;
1281 /* if this is a static variable & has an */
1282 /* initial value the code needs to be lifted */
1283 /* here to the main portion since they can be */
1284 /* initialised only once at the start */
1285 if (IS_STATIC (sym->etype) && sym->ival &&
1286 SPEC_SCLS (sym->etype) != S_CODE)
1290 /* insert the symbol into the symbol table */
1291 /* with level = 0 & name = rname */
1292 newSym = copySymbol (sym);
1293 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1295 /* now lift the code to main */
1296 if (IS_AGGREGATE (sym->type)) {
1297 work = initAggregates (sym, sym->ival, NULL);
1299 if (getNelements(sym->type, sym->ival)>1) {
1300 werrorfl (sym->fileDef, sym->lineDef,
1301 W_EXCESS_INITIALIZERS, "scalar",
1304 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1305 list2expr (sym->ival));
1308 setAstFileLine (work, sym->fileDef, sym->lineDef);
1312 staticAutos = newNode (NULLOP, staticAutos, work);
1319 /* if there is an initial value */
1320 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1322 initList *ilist=sym->ival;
1324 while (ilist->type == INIT_DEEP) {
1325 ilist = ilist->init.deep;
1328 /* update lineno for error msg */
1329 filename = sym->fileDef;
1330 lineno = sym->lineDef;
1331 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1333 if (IS_AGGREGATE (sym->type)) {
1334 work = initAggregates (sym, sym->ival, NULL);
1336 if (getNelements(sym->type, sym->ival)>1) {
1337 werrorfl (sym->fileDef, sym->lineDef,
1338 W_EXCESS_INITIALIZERS, "scalar",
1341 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1342 list2expr (sym->ival));
1346 setAstFileLine (work, sym->fileDef, sym->lineDef);
1350 init = newNode (NULLOP, init, work);
1359 /*-----------------------------------------------------------------*/
1360 /* freeStringSymbol - delete a literal string if no more usage */
1361 /*-----------------------------------------------------------------*/
1362 void freeStringSymbol(symbol *sym) {
1363 /* make sure this is a literal string */
1364 assert (sym->isstrlit);
1365 if (--sym->isstrlit == 0) { // lower the usage count
1366 memmap *segment=SPEC_OCLS(sym->etype);
1368 deleteSetItem(&segment->syms, sym);
1373 /*-----------------------------------------------------------------*/
1374 /* stringToSymbol - creates a symbol from a literal string */
1375 /*-----------------------------------------------------------------*/
1377 stringToSymbol (value * val)
1379 char name[SDCC_NAME_MAX + 1];
1380 static int charLbl = 0;
1385 // have we heard this before?
1386 for (sp = statsg->syms; sp; sp = sp->next)
1389 size = getSize (sym->type);
1390 if (sym->isstrlit && size == getSize (val->type) &&
1391 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1393 // yes, this is old news. Don't publish it again.
1394 sym->isstrlit++; // but raise the usage count
1395 return symbolVal (sym);
1399 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1400 sym = newSymbol (name, 0); /* make it @ level 0 */
1401 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1403 /* copy the type from the value passed */
1404 sym->type = copyLinkChain (val->type);
1405 sym->etype = getSpec (sym->type);
1406 /* change to storage class & output class */
1407 SPEC_SCLS (sym->etype) = S_CODE;
1408 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1409 SPEC_STAT (sym->etype) = 1;
1410 /* make the level & block = 0 */
1411 sym->block = sym->level = 0;
1413 /* create an ival */
1414 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1419 allocVariables (sym);
1422 return symbolVal (sym);
1426 /*-----------------------------------------------------------------*/
1427 /* processBlockVars - will go thru the ast looking for block if */
1428 /* a block is found then will allocate the syms */
1429 /* will also gather the auto inits present */
1430 /*-----------------------------------------------------------------*/
1432 processBlockVars (ast * tree, int *stack, int action)
1437 /* if this is a block */
1438 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1442 if (action == ALLOCATE)
1444 *stack += allocVariables (tree->values.sym);
1445 autoInit = gatherAutoInit (tree->values.sym);
1447 /* if there are auto inits then do them */
1449 tree->left = newNode (NULLOP, autoInit, tree->left);
1451 else /* action is deallocate */
1452 deallocLocal (tree->values.sym);
1455 processBlockVars (tree->left, stack, action);
1456 processBlockVars (tree->right, stack, action);
1461 /*-------------------------------------------------------------*/
1462 /* constExprTree - returns TRUE if this tree is a constant */
1464 /*-------------------------------------------------------------*/
1465 bool constExprTree (ast *cexpr) {
1471 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1473 switch (cexpr->type)
1476 if (IS_AST_LIT_VALUE(cexpr)) {
1477 // this is a literal
1480 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1481 // a function's address will never change
1484 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1485 // an array's address will never change
1488 if (IS_AST_SYM_VALUE(cexpr) &&
1489 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1490 // a symbol in code space will never change
1491 // This is only for the 'char *s="hallo"' case and will have to leave
1492 //printf(" code space symbol");
1497 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498 "unexpected link in expression tree\n");
1501 if (cexpr->opval.op==ARRAYINIT) {
1502 // this is a list of literals
1505 if (cexpr->opval.op=='=') {
1506 return constExprTree(cexpr->right);
1508 if (cexpr->opval.op==CAST) {
1509 // cast ignored, maybe we should throw a warning here?
1510 return constExprTree(cexpr->right);
1512 if (cexpr->opval.op=='&') {
1515 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1518 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1523 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1528 /*-----------------------------------------------------------------*/
1529 /* constExprValue - returns the value of a constant expression */
1530 /* or NULL if it is not a constant expression */
1531 /*-----------------------------------------------------------------*/
1533 constExprValue (ast * cexpr, int check)
1535 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1537 /* if this is not a constant then */
1538 if (!IS_LITERAL (cexpr->ftype))
1540 /* then check if this is a literal array
1542 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1543 SPEC_CVAL (cexpr->etype).v_char &&
1544 IS_ARRAY (cexpr->ftype))
1546 value *val = valFromType (cexpr->ftype);
1547 SPEC_SCLS (val->etype) = S_LITERAL;
1548 val->sym = cexpr->opval.val->sym;
1549 val->sym->type = copyLinkChain (cexpr->ftype);
1550 val->sym->etype = getSpec (val->sym->type);
1551 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1555 /* if we are casting a literal value then */
1556 if (IS_AST_OP (cexpr) &&
1557 cexpr->opval.op == CAST &&
1558 IS_LITERAL (cexpr->right->ftype))
1560 return valCastLiteral (cexpr->ftype,
1561 floatFromVal (cexpr->right->opval.val));
1564 if (IS_AST_VALUE (cexpr))
1566 return cexpr->opval.val;
1570 werror (E_CONST_EXPECTED, "found expression");
1575 /* return the value */
1576 if (IS_AST_VALUE (cexpr))
1578 return cexpr->opval.val;
1583 /*-----------------------------------------------------------------*/
1584 /* isLabelInAst - will return true if a given label is found */
1585 /*-----------------------------------------------------------------*/
1587 isLabelInAst (symbol * label, ast * tree)
1589 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1592 if (IS_AST_OP (tree) &&
1593 tree->opval.op == LABEL &&
1594 isSymbolEqual (AST_SYMBOL (tree->left), label))
1597 return isLabelInAst (label, tree->right) &&
1598 isLabelInAst (label, tree->left);
1601 /*-----------------------------------------------------------------*/
1602 /* isLoopCountable - return true if the loop count can be determi- */
1603 /* -ned at compile time . */
1604 /*-----------------------------------------------------------------*/
1606 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1607 symbol ** sym, ast ** init, ast ** end)
1610 /* the loop is considered countable if the following
1611 conditions are true :-
1613 a) initExpr :- <sym> = <const>
1614 b) condExpr :- <sym> < <const1>
1615 c) loopExpr :- <sym> ++
1618 /* first check the initExpr */
1619 if (IS_AST_OP (initExpr) &&
1620 initExpr->opval.op == '=' && /* is assignment */
1621 IS_AST_SYM_VALUE (initExpr->left))
1622 { /* left is a symbol */
1624 *sym = AST_SYMBOL (initExpr->left);
1625 *init = initExpr->right;
1630 /* don't reverse loop with volatile counter */
1631 if (IS_VOLATILE ((*sym)->type))
1634 /* for now the symbol has to be of
1636 if (!IS_INTEGRAL ((*sym)->type))
1639 /* now check condExpr */
1640 if (IS_AST_OP (condExpr))
1643 switch (condExpr->opval.op)
1646 if (IS_AST_SYM_VALUE (condExpr->left) &&
1647 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1648 IS_AST_LIT_VALUE (condExpr->right))
1650 *end = condExpr->right;
1656 if (IS_AST_OP (condExpr->left) &&
1657 condExpr->left->opval.op == '>' &&
1658 IS_AST_LIT_VALUE (condExpr->left->right) &&
1659 IS_AST_SYM_VALUE (condExpr->left->left) &&
1660 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1663 *end = newNode ('+', condExpr->left->right,
1664 newAst_VALUE (constCharVal (1)));
1677 /* check loop expression is of the form <sym>++ */
1678 if (!IS_AST_OP (loopExpr))
1681 /* check if <sym> ++ */
1682 if (loopExpr->opval.op == INC_OP)
1688 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1689 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1696 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1697 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1705 if (loopExpr->opval.op == ADD_ASSIGN)
1708 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1709 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1710 IS_AST_LIT_VALUE (loopExpr->right) &&
1711 AST_ULONG_VALUE (loopExpr->right) != 1)
1719 /*-----------------------------------------------------------------*/
1720 /* astHasVolatile - returns true if ast contains any volatile */
1721 /*-----------------------------------------------------------------*/
1723 astHasVolatile (ast * tree)
1728 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1731 if (IS_AST_OP (tree))
1732 return astHasVolatile (tree->left) ||
1733 astHasVolatile (tree->right);
1738 /*-----------------------------------------------------------------*/
1739 /* astHasPointer - return true if the ast contains any ptr variable */
1740 /*-----------------------------------------------------------------*/
1742 astHasPointer (ast * tree)
1747 if (IS_AST_LINK (tree))
1750 /* if we hit an array expression then check
1751 only the left side */
1752 if (IS_AST_OP (tree) && tree->opval.op == '[')
1753 return astHasPointer (tree->left);
1755 if (IS_AST_VALUE (tree))
1756 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1758 return astHasPointer (tree->left) ||
1759 astHasPointer (tree->right);
1763 /*-----------------------------------------------------------------*/
1764 /* astHasSymbol - return true if the ast has the given symbol */
1765 /*-----------------------------------------------------------------*/
1767 astHasSymbol (ast * tree, symbol * sym)
1769 if (!tree || IS_AST_LINK (tree))
1772 if (IS_AST_VALUE (tree))
1774 if (IS_AST_SYM_VALUE (tree))
1775 return isSymbolEqual (AST_SYMBOL (tree), sym);
1780 return astHasSymbol (tree->left, sym) ||
1781 astHasSymbol (tree->right, sym);
1784 /*-----------------------------------------------------------------*/
1785 /* astHasDeref - return true if the ast has an indirect access */
1786 /*-----------------------------------------------------------------*/
1788 astHasDeref (ast * tree)
1790 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1793 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1795 return astHasDeref (tree->left) || astHasDeref (tree->right);
1798 /*-----------------------------------------------------------------*/
1799 /* isConformingBody - the loop body has to conform to a set of rules */
1800 /* for the loop to be considered reversible read on for rules */
1801 /*-----------------------------------------------------------------*/
1803 isConformingBody (ast * pbody, symbol * sym, ast * body)
1806 /* we are going to do a pre-order traversal of the
1807 tree && check for the following conditions. (essentially
1808 a set of very shallow tests )
1809 a) the sym passed does not participate in
1810 any arithmetic operation
1811 b) There are no function calls
1812 c) all jumps are within the body
1813 d) address of loop control variable not taken
1814 e) if an assignment has a pointer on the
1815 left hand side make sure right does not have
1816 loop control variable */
1818 /* if we reach the end or a leaf then true */
1819 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1822 /* if anything else is "volatile" */
1823 if (IS_VOLATILE (TETYPE (pbody)))
1826 /* we will walk the body in a pre-order traversal for
1828 switch (pbody->opval.op)
1830 /*------------------------------------------------------------------*/
1832 // if the loopvar is used as an index
1833 /* array op is commutative -- must check both left & right */
1834 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1837 return isConformingBody (pbody->right, sym, body)
1838 && isConformingBody (pbody->left, sym, body);
1840 /*------------------------------------------------------------------*/
1845 /*------------------------------------------------------------------*/
1849 /* sure we are not sym is not modified */
1851 IS_AST_SYM_VALUE (pbody->left) &&
1852 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1856 IS_AST_SYM_VALUE (pbody->right) &&
1857 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1862 /*------------------------------------------------------------------*/
1864 case '*': /* can be unary : if right is null then unary operation */
1869 /* if right is NULL then unary operation */
1870 /*------------------------------------------------------------------*/
1871 /*----------------------------*/
1873 /*----------------------------*/
1876 if (IS_AST_SYM_VALUE (pbody->left) &&
1877 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1880 return isConformingBody (pbody->left, sym, body);
1884 if (astHasSymbol (pbody->left, sym) ||
1885 astHasSymbol (pbody->right, sym))
1890 /*------------------------------------------------------------------*/
1901 if (IS_AST_SYM_VALUE (pbody->left) &&
1902 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1905 if (IS_AST_SYM_VALUE (pbody->right) &&
1906 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1909 return isConformingBody (pbody->left, sym, body) &&
1910 isConformingBody (pbody->right, sym, body);
1918 if (IS_AST_SYM_VALUE (pbody->left) &&
1919 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1921 return isConformingBody (pbody->left, sym, body);
1923 /*------------------------------------------------------------------*/
1935 case SIZEOF: /* evaluate wihout code generation */
1937 if (IS_AST_SYM_VALUE (pbody->left) &&
1938 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1941 if (IS_AST_SYM_VALUE (pbody->right) &&
1942 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1945 return isConformingBody (pbody->left, sym, body) &&
1946 isConformingBody (pbody->right, sym, body);
1948 /*------------------------------------------------------------------*/
1951 /* if left has a pointer & right has loop
1952 control variable then we cannot */
1953 if (astHasPointer (pbody->left) &&
1954 astHasSymbol (pbody->right, sym))
1956 if (astHasVolatile (pbody->left))
1959 if (IS_AST_SYM_VALUE (pbody->left)) {
1960 // if the loopvar has an assignment
1961 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1963 // if the loopvar is used in another (maybe conditional) block
1964 if (astHasSymbol (pbody->right, sym) &&
1965 (pbody->level >= body->level)) {
1970 if (astHasVolatile (pbody->left))
1973 if (astHasDeref(pbody->right)) return FALSE;
1975 return isConformingBody (pbody->left, sym, body) &&
1976 isConformingBody (pbody->right, sym, body);
1987 assert ("Parser should not have generated this\n");
1989 /*------------------------------------------------------------------*/
1990 /*----------------------------*/
1991 /* comma operator */
1992 /*----------------------------*/
1994 return isConformingBody (pbody->left, sym, body) &&
1995 isConformingBody (pbody->right, sym, body);
1997 /*------------------------------------------------------------------*/
1998 /*----------------------------*/
2000 /*----------------------------*/
2002 /* if local & not passed as paramater then ok */
2003 if (sym->level && !astHasSymbol(pbody->right,sym))
2007 /*------------------------------------------------------------------*/
2008 /*----------------------------*/
2009 /* return statement */
2010 /*----------------------------*/
2015 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2020 if (astHasSymbol (pbody->left, sym))
2027 return isConformingBody (pbody->left, sym, body) &&
2028 isConformingBody (pbody->right, sym, body);
2034 /*-----------------------------------------------------------------*/
2035 /* isLoopReversible - takes a for loop as input && returns true */
2036 /* if the for loop is reversible. If yes will set the value of */
2037 /* the loop control var & init value & termination value */
2038 /*-----------------------------------------------------------------*/
2040 isLoopReversible (ast * loop, symbol ** loopCntrl,
2041 ast ** init, ast ** end)
2043 /* if option says don't do it then don't */
2044 if (optimize.noLoopReverse)
2046 /* there are several tests to determine this */
2048 /* for loop has to be of the form
2049 for ( <sym> = <const1> ;
2050 [<sym> < <const2>] ;
2051 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2053 if (!isLoopCountable (AST_FOR (loop, initExpr),
2054 AST_FOR (loop, condExpr),
2055 AST_FOR (loop, loopExpr),
2056 loopCntrl, init, end))
2059 /* now do some serious checking on the body of the loop
2062 return isConformingBody (loop->left, *loopCntrl, loop->left);
2066 /*-----------------------------------------------------------------*/
2067 /* replLoopSym - replace the loop sym by loop sym -1 */
2068 /*-----------------------------------------------------------------*/
2070 replLoopSym (ast * body, symbol * sym)
2073 if (!body || IS_AST_LINK (body))
2076 if (IS_AST_SYM_VALUE (body))
2079 if (isSymbolEqual (AST_SYMBOL (body), sym))
2083 body->opval.op = '-';
2084 body->left = newAst_VALUE (symbolVal (sym));
2085 body->right = newAst_VALUE (constCharVal (1));
2093 replLoopSym (body->left, sym);
2094 replLoopSym (body->right, sym);
2098 /*-----------------------------------------------------------------*/
2099 /* reverseLoop - do the actual loop reversal */
2100 /*-----------------------------------------------------------------*/
2102 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2106 /* create the following tree
2111 if (sym) goto for_continue ;
2114 /* put it together piece by piece */
2115 rloop = newNode (NULLOP,
2116 createIf (newAst_VALUE (symbolVal (sym)),
2118 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2121 newAst_VALUE (symbolVal (sym)),
2124 replLoopSym (loop->left, sym);
2125 setAstFileLine (rloop, init->filename, init->lineno);
2127 rloop = newNode (NULLOP,
2129 newAst_VALUE (symbolVal (sym)),
2130 newNode ('-', end, init)),
2131 createLabel (AST_FOR (loop, continueLabel),
2135 newNode (SUB_ASSIGN,
2136 newAst_VALUE (symbolVal (sym)),
2137 newAst_VALUE (constCharVal (1))),
2140 rloop->lineno=init->lineno;
2141 return decorateType (rloop, RESULT_TYPE_NONE);
2145 /*-----------------------------------------------------------------*/
2146 /* searchLitOp - search tree (*ops only) for an ast with literal */
2147 /*-----------------------------------------------------------------*/
2149 searchLitOp (ast *tree, ast **parent, const char *ops)
2153 if (tree && optimize.global_cse)
2155 /* is there a literal operand? */
2157 IS_AST_OP(tree->right) &&
2158 tree->right->right &&
2159 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2161 if (IS_LITERAL (RTYPE (tree->right)) !=
2162 IS_LITERAL (LTYPE (tree->right)))
2164 tree->right->decorated = 0;
2165 tree->decorated = 0;
2169 ret = searchLitOp (tree->right, parent, ops);
2174 IS_AST_OP(tree->left) &&
2175 tree->left->right &&
2176 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2178 if (IS_LITERAL (RTYPE (tree->left)) !=
2179 IS_LITERAL (LTYPE (tree->left)))
2181 tree->left->decorated = 0;
2182 tree->decorated = 0;
2186 ret = searchLitOp (tree->left, parent, ops);
2194 /*-----------------------------------------------------------------*/
2195 /* getResultFromType */
2196 /*-----------------------------------------------------------------*/
2198 getResultTypeFromType (sym_link *type)
2200 /* type = getSpec (type); */
2202 return RESULT_TYPE_BIT;
2203 if (IS_BITFIELD (type))
2205 int blen = SPEC_BLEN (type);
2208 return RESULT_TYPE_BIT;
2210 return RESULT_TYPE_CHAR;
2211 return RESULT_TYPE_INT;
2214 return RESULT_TYPE_CHAR;
2215 if (IS_INT (type) && !IS_LONG (type))
2216 return RESULT_TYPE_INT;
2217 return RESULT_TYPE_OTHER;
2220 /*-----------------------------------------------------------------*/
2221 /* addCast - adds casts to a type specified by RESULT_TYPE */
2222 /*-----------------------------------------------------------------*/
2224 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2227 bool upCasted = FALSE;
2231 case RESULT_TYPE_NONE:
2232 /* if thing smaller than int must be promoted to int */
2234 getSize (tree->etype) >= INTSIZE)
2235 /* promotion not necessary or already an int */
2237 /* char and bits: promote to int */
2238 newLink = newIntLink();
2241 case RESULT_TYPE_BIT:
2243 /* already an int */
2244 bitsForType (tree->etype) >= 16 ||
2245 /* bit to bit operation: don't promote, the code generators
2246 hopefully know everything about promotion rules */
2247 bitsForType (tree->etype) == 1)
2249 newLink = newIntLink();
2252 case RESULT_TYPE_CHAR:
2253 if (IS_CHAR (tree->etype) ||
2254 IS_FLOAT(tree->etype) ||
2255 IS_FIXED(tree->etype))
2257 newLink = newCharLink();
2259 case RESULT_TYPE_INT:
2261 if (getSize (tree->etype) > INTSIZE)
2263 /* warn ("Loosing significant digits"); */
2267 /* char: promote to int */
2269 getSize (tree->etype) >= INTSIZE)
2271 newLink = newIntLink();
2274 case RESULT_TYPE_IFX:
2275 case RESULT_TYPE_OTHER:
2277 /* return type is ifx, long, float: promote char to int */
2278 getSize (tree->etype) >= INTSIZE)
2280 newLink = newIntLink();
2286 tree->decorated = 0;
2287 tree = newNode (CAST, newAst_LINK (newLink), tree);
2288 tree->filename = tree->right->filename;
2289 tree->lineno = tree->right->lineno;
2290 /* keep unsigned type during cast to smaller type,
2291 but not when promoting from char to int */
2293 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2294 return decorateType (tree, resultType);
2297 /*-----------------------------------------------------------------*/
2298 /* resultTypePropagate - decides if resultType can be propagated */
2299 /*-----------------------------------------------------------------*/
2301 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2303 switch (tree->opval.op)
2320 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2321 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2322 return RESULT_TYPE_NONE;
2327 return RESULT_TYPE_NONE;
2331 return RESULT_TYPE_IFX;
2333 return RESULT_TYPE_NONE;
2337 /*-----------------------------------------------------------------*/
2338 /* getLeftResultType - gets type from left branch for propagation */
2339 /*-----------------------------------------------------------------*/
2341 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2343 switch (tree->opval.op)
2347 if (IS_PTR (LTYPE (tree)))
2348 return RESULT_TYPE_NONE;
2350 return getResultTypeFromType (LETYPE (tree));
2352 if (IS_PTR (currFunc->type->next))
2353 return RESULT_TYPE_NONE;
2355 return getResultTypeFromType (currFunc->type->next);
2357 if (!IS_ARRAY (LTYPE (tree)))
2359 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2360 return RESULT_TYPE_CHAR;
2367 /*------------------------------------------------------------------*/
2368 /* gatherImplicitVariables: assigns correct type information to */
2369 /* symbols and values created by replaceAstWithTemporary */
2370 /* and adds the symbols to the declarations list of the */
2371 /* innermost block that contains them */
2372 /*------------------------------------------------------------------*/
2374 gatherImplicitVariables (ast * tree, ast * block)
2379 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2381 /* keep track of containing scope */
2384 if (tree->type == EX_OP && tree->opval.op == '=' &&
2385 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2387 symbol *assignee = tree->left->opval.val->sym;
2389 /* special case for assignment to compiler-generated temporary variable:
2390 compute type of RHS, and set the symbol's type to match */
2391 if (assignee->type == NULL && assignee->infertype) {
2392 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2394 if (dtr != tree->right)
2397 assignee->type = copyLinkChain(TTYPE(dtr));
2398 assignee->etype = getSpec(assignee->type);
2399 SPEC_SCLS (assignee->etype) = S_AUTO;
2400 SPEC_OCLS (assignee->etype) = NULL;
2401 SPEC_EXTR (assignee->etype) = 0;
2402 SPEC_STAT (assignee->etype) = 0;
2403 SPEC_VOLATILE (assignee->etype) = 0;
2404 SPEC_ABSA (assignee->etype) = 0;
2406 wassertl(block != NULL, "implicit variable not contained in block");
2407 wassert(assignee->next == NULL);
2408 if (block != NULL) {
2409 symbol **decl = &(block->values.sym);
2412 wassert(*decl != assignee); /* should not already be in list */
2413 decl = &( (*decl)->next );
2420 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2421 tree->opval.val->type == NULL &&
2422 tree->opval.val->sym &&
2423 tree->opval.val->sym->infertype)
2425 /* fixup type of value for compiler-inferred temporary var */
2426 tree->opval.val->type = tree->opval.val->sym->type;
2427 tree->opval.val->etype = tree->opval.val->sym->etype;
2430 gatherImplicitVariables(tree->left, block);
2431 gatherImplicitVariables(tree->right, block);
2434 /*--------------------------------------------------------------------*/
2435 /* decorateType - compute type for this tree, also does type checking.*/
2436 /* This is done bottom up, since type has to flow upwards. */
2437 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2438 /* result is a char and the operand(s) are int's. */
2439 /* It also does constant folding, and parameter checking. */
2440 /*--------------------------------------------------------------------*/
2442 decorateType (ast * tree, RESULT_TYPE resultType)
2446 RESULT_TYPE resultTypeProp;
2451 /* if already has type then do nothing */
2452 if (tree->decorated)
2455 tree->decorated = 1;
2458 /* print the line */
2459 /* if not block & function */
2460 if (tree->type == EX_OP &&
2461 (tree->opval.op != FUNCTION &&
2462 tree->opval.op != BLOCK &&
2463 tree->opval.op != NULLOP))
2465 filename = tree->filename;
2466 lineno = tree->lineno;
2470 /* if any child is an error | this one is an error do nothing */
2471 if (tree->isError ||
2472 (tree->left && tree->left->isError) ||
2473 (tree->right && tree->right->isError))
2476 /*------------------------------------------------------------------*/
2477 /*----------------------------*/
2478 /* leaf has been reached */
2479 /*----------------------------*/
2480 filename = tree->filename;
2481 lineno = tree->lineno;
2482 /* if this is of type value */
2483 /* just get the type */
2484 if (tree->type == EX_VALUE)
2487 if (IS_LITERAL (tree->opval.val->etype))
2490 /* if this is a character array then declare it */
2491 if (IS_ARRAY (tree->opval.val->type))
2492 tree->opval.val = stringToSymbol (tree->opval.val);
2494 /* otherwise just copy the type information */
2495 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2499 if (tree->opval.val->sym)
2501 /* if the undefined flag is set then give error message */
2502 if (tree->opval.val->sym->undefined)
2504 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2506 TTYPE (tree) = TETYPE (tree) =
2507 tree->opval.val->type = tree->opval.val->sym->type =
2508 tree->opval.val->etype = tree->opval.val->sym->etype =
2509 copyLinkChain (INTTYPE);
2511 else if (tree->opval.val->sym->implicit)
2513 /* if implicit i.e. struct/union member then no type */
2514 TTYPE (tree) = TETYPE (tree) = NULL;
2518 /* copy the type from the value into the ast */
2519 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2521 /* and mark the symbol as referenced */
2522 tree->opval.val->sym->isref = 1;
2526 wassert(0); /* unreached: all values are literals or symbols */
2531 /* if type link for the case of cast */
2532 if (tree->type == EX_LINK)
2534 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2542 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2544 if (tree->left && tree->left->type == EX_OPERAND
2545 && (tree->left->opval.op == INC_OP
2546 || tree->left->opval.op == DEC_OP)
2547 && tree->left->left)
2549 tree->left->right = tree->left->left;
2550 tree->left->left = NULL;
2552 if (tree->right && tree->right->type == EX_OPERAND
2553 && (tree->right->opval.op == INC_OP
2554 || tree->right->opval.op == DEC_OP)
2555 && tree->right->left)
2557 tree->right->right = tree->right->left;
2558 tree->right->left = NULL;
2563 /* Before decorating the left branch we've to decide in dependence
2564 upon tree->opval.op, if resultType can be propagated */
2565 resultTypeProp = resultTypePropagate (tree, resultType);
2567 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2568 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2570 dtl = decorateType (tree->left, resultTypeProp);
2572 /* if an array node, we may need to swap branches */
2573 if (tree->opval.op == '[')
2575 /* determine which is the array & which the index */
2576 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2577 IS_INTEGRAL (LTYPE (tree)))
2579 ast *tempTree = tree->left;
2580 tree->left = tree->right;
2581 tree->right = tempTree;
2585 /* After decorating the left branch there's type information available
2586 in tree->left->?type. If the op is e.g. '=' we extract the type
2587 information from there and propagate it to the right branch. */
2588 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2590 switch (tree->opval.op)
2593 /* delay right side for '?' operator since conditional macro
2594 expansions might rely on this */
2598 /* decorate right side for CALL (parameter list) in processParms();
2599 there is resultType available */
2603 /* don't allocate string if it is a sizeof argument */
2605 dtr = decorateType (tree->right, resultTypeProp);
2609 dtr = decorateType (tree->right, resultTypeProp);
2613 /* this is to take care of situations
2614 when the tree gets rewritten */
2615 if (dtl != tree->left)
2617 if (dtr != tree->right)
2619 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2623 /* depending on type of operator do */
2625 switch (tree->opval.op)
2627 /*------------------------------------------------------------------*/
2628 /*----------------------------*/
2630 /*----------------------------*/
2633 /* first check if this is a array or a pointer */
2634 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2636 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2637 goto errorTreeReturn;
2640 /* check if the type of the idx */
2641 if (!IS_INTEGRAL (RTYPE (tree)))
2643 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2644 goto errorTreeReturn;
2647 /* if the left is an rvalue then error */
2650 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2651 goto errorTreeReturn;
2654 if (IS_LITERAL (RTYPE (tree)))
2656 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2657 int arraySize = DCL_ELEM (LTYPE (tree));
2658 if (arraySize && arrayIndex >= arraySize)
2660 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2665 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2666 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2669 /*------------------------------------------------------------------*/
2670 /*----------------------------*/
2672 /*----------------------------*/
2674 /* if this is not a structure */
2675 if (!IS_STRUCT (LTYPE (tree)))
2677 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2678 goto errorTreeReturn;
2680 TTYPE (tree) = structElemType (LTYPE (tree),
2681 (tree->right->type == EX_VALUE ?
2682 tree->right->opval.val : NULL));
2683 TETYPE (tree) = getSpec (TTYPE (tree));
2686 /*------------------------------------------------------------------*/
2687 /*----------------------------*/
2688 /* struct/union pointer */
2689 /*----------------------------*/
2691 /* if not pointer to a structure */
2692 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2694 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2695 goto errorTreeReturn;
2698 if (!IS_STRUCT (LTYPE (tree)->next))
2700 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2701 goto errorTreeReturn;
2704 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2705 (tree->right->type == EX_VALUE ?
2706 tree->right->opval.val : NULL));
2707 TETYPE (tree) = getSpec (TTYPE (tree));
2709 /* adjust the storage class */
2710 switch (DCL_TYPE(tree->left->ftype)) {
2712 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2715 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2718 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2721 SPEC_SCLS (TETYPE (tree)) = 0;
2724 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2727 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2730 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2733 SPEC_SCLS (TETYPE (tree)) = 0;
2740 /* This breaks with extern declarations, bitfields, and perhaps other */
2741 /* cases (gcse). Let's leave this optimization disabled for now and */
2742 /* ponder if there's a safe way to do this. -- EEP */
2744 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2745 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2747 /* If defined struct type at addr var
2748 then rewrite (&struct var)->member
2750 and define membertype at (addr+offsetof(struct var,member)) temp
2753 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2754 AST_SYMBOL(tree->right));
2756 sym = newSymbol(genSymName (0), 0);
2757 sym->type = TTYPE (tree);
2758 sym->etype = getSpec(sym->type);
2759 sym->lineDef = tree->lineno;
2762 SPEC_STAT (sym->etype) = 1;
2763 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2765 SPEC_ABSA(sym->etype) = 1;
2766 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2769 AST_VALUE (tree) = symbolVal(sym);
2772 tree->type = EX_VALUE;
2780 /*------------------------------------------------------------------*/
2781 /*----------------------------*/
2782 /* ++/-- operation */
2783 /*----------------------------*/
2787 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2788 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2789 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2790 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2799 /*------------------------------------------------------------------*/
2800 /*----------------------------*/
2802 /*----------------------------*/
2803 case '&': /* can be unary */
2804 /* if right is NULL then unary operation */
2805 if (tree->right) /* not an unary operation */
2808 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2810 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2811 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2812 printTypeChain (LTYPE (tree), stderr);
2813 fprintf (stderr, ",");
2814 printTypeChain (RTYPE (tree), stderr);
2815 fprintf (stderr, "\n");
2816 goto errorTreeReturn;
2819 /* if they are both literal */
2820 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2822 tree->type = EX_VALUE;
2823 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2824 valFromType (RETYPE (tree)), '&');
2826 tree->right = tree->left = NULL;
2827 TETYPE (tree) = tree->opval.val->etype;
2828 TTYPE (tree) = tree->opval.val->type;
2832 /* see if this is a GETHBIT operation if yes
2835 ast *otree = optimizeGetHbit (tree, resultType);
2838 return decorateType (otree, RESULT_TYPE_NONE);
2841 /* see if this is a GETABIT operation if yes
2844 ast *otree = optimizeGetAbit (tree, resultType);
2847 return decorateType (otree, RESULT_TYPE_NONE);
2850 /* see if this is a GETBYTE operation if yes
2853 ast *otree = optimizeGetByte (tree, resultType);
2856 return decorateType (otree, RESULT_TYPE_NONE);
2859 /* see if this is a GETWORD operation if yes
2862 ast *otree = optimizeGetWord (tree, resultType);
2865 return decorateType (otree, RESULT_TYPE_NONE);
2868 /* if left is a literal exchange left & right */
2869 if (IS_LITERAL (LTYPE (tree)))
2871 ast *tTree = tree->left;
2872 tree->left = tree->right;
2873 tree->right = tTree;
2876 /* if right is a literal and */
2877 /* we can find a 2nd literal in an and-tree then */
2878 /* rearrange the tree */
2879 if (IS_LITERAL (RTYPE (tree)))
2882 ast *litTree = searchLitOp (tree, &parent, "&");
2886 ast *tTree = litTree->left;
2887 litTree->left = tree->right;
2888 tree->right = tTree;
2889 /* both operands in litTree are literal now */
2890 decorateType (parent, resultType);
2894 LRVAL (tree) = RRVAL (tree) = 1;
2896 TTYPE (tree) = computeType (LTYPE (tree),
2900 TETYPE (tree) = getSpec (TTYPE (tree));
2905 /*------------------------------------------------------------------*/
2906 /*----------------------------*/
2908 /*----------------------------*/
2909 p = newLink (DECLARATOR);
2910 /* if bit field then error */
2911 if (IS_BITVAR (tree->left->etype))
2913 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2914 goto errorTreeReturn;
2917 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2919 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2920 goto errorTreeReturn;
2923 if (IS_FUNC (LTYPE (tree)))
2925 // this ought to be ignored
2926 return (tree->left);
2929 if (IS_LITERAL(LTYPE(tree)))
2931 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2932 goto errorTreeReturn;
2937 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2938 goto errorTreeReturn;
2941 DCL_TYPE (p) = POINTER;
2942 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2943 DCL_TYPE (p) = CPOINTER;
2944 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2945 DCL_TYPE (p) = FPOINTER;
2946 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2947 DCL_TYPE (p) = PPOINTER;
2948 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2949 DCL_TYPE (p) = IPOINTER;
2950 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2951 DCL_TYPE (p) = EEPPOINTER;
2952 else if (SPEC_OCLS(tree->left->etype))
2953 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2955 DCL_TYPE (p) = POINTER;
2957 if (IS_AST_SYM_VALUE (tree->left))
2959 AST_SYMBOL (tree->left)->addrtaken = 1;
2960 AST_SYMBOL (tree->left)->allocreq = 1;
2963 p->next = LTYPE (tree);
2965 TETYPE (tree) = getSpec (TTYPE (tree));
2970 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2971 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2973 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2974 AST_SYMBOL(tree->left->right));
2975 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2976 valueFromLit(element->offset));
2979 tree->type = EX_VALUE;
2980 tree->values.literalFromCast = 1;
2986 /*------------------------------------------------------------------*/
2987 /*----------------------------*/
2989 /*----------------------------*/
2991 /* if the rewrite succeeds then don't go any further */
2993 ast *wtree = optimizeRRCRLC (tree);
2995 return decorateType (wtree, RESULT_TYPE_NONE);
2997 wtree = optimizeSWAP (tree);
2999 return decorateType (wtree, RESULT_TYPE_NONE);
3002 /* if left is a literal exchange left & right */
3003 if (IS_LITERAL (LTYPE (tree)))
3005 ast *tTree = tree->left;
3006 tree->left = tree->right;
3007 tree->right = tTree;
3010 /* if right is a literal and */
3011 /* we can find a 2nd literal in an or-tree then */
3012 /* rearrange the tree */
3013 if (IS_LITERAL (RTYPE (tree)))
3016 ast *litTree = searchLitOp (tree, &parent, "|");
3020 ast *tTree = litTree->left;
3021 litTree->left = tree->right;
3022 tree->right = tTree;
3023 /* both operands in tTree are literal now */
3024 decorateType (parent, resultType);
3029 /*------------------------------------------------------------------*/
3030 /*----------------------------*/
3032 /*----------------------------*/
3034 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3036 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3037 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3038 printTypeChain (LTYPE (tree), stderr);
3039 fprintf (stderr, ",");
3040 printTypeChain (RTYPE (tree), stderr);
3041 fprintf (stderr, "\n");
3042 goto errorTreeReturn;
3045 /* if they are both literal then rewrite the tree */
3046 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3048 tree->type = EX_VALUE;
3049 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3050 valFromType (RETYPE (tree)),
3052 tree->right = tree->left = NULL;
3053 TETYPE (tree) = tree->opval.val->etype;
3054 TTYPE (tree) = tree->opval.val->type;
3058 /* if left is a literal exchange left & right */
3059 if (IS_LITERAL (LTYPE (tree)))
3061 ast *tTree = tree->left;
3062 tree->left = tree->right;
3063 tree->right = tTree;
3066 /* if right is a literal and */
3067 /* we can find a 2nd literal in a xor-tree then */
3068 /* rearrange the tree */
3069 if (IS_LITERAL (RTYPE (tree)) &&
3070 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3073 ast *litTree = searchLitOp (tree, &parent, "^");
3077 ast *tTree = litTree->left;
3078 litTree->left = tree->right;
3079 tree->right = tTree;
3080 /* both operands in litTree are literal now */
3081 decorateType (parent, resultType);
3085 LRVAL (tree) = RRVAL (tree) = 1;
3087 TTYPE (tree) = computeType (LTYPE (tree),
3091 TETYPE (tree) = getSpec (TTYPE (tree));
3095 /*------------------------------------------------------------------*/
3096 /*----------------------------*/
3098 /*----------------------------*/
3100 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3102 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3103 goto errorTreeReturn;
3105 /* if they are both literal then */
3106 /* rewrite the tree */
3107 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3109 tree->type = EX_VALUE;
3110 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3111 valFromType (RETYPE (tree)));
3112 tree->right = tree->left = NULL;
3113 TETYPE (tree) = getSpec (TTYPE (tree) =
3114 tree->opval.val->type);
3118 LRVAL (tree) = RRVAL (tree) = 1;
3120 TETYPE (tree) = getSpec (TTYPE (tree) =
3121 computeType (LTYPE (tree),
3126 /* if right is a literal and */
3127 /* left is also a division by a literal then */
3128 /* rearrange the tree */
3129 if (IS_LITERAL (RTYPE (tree))
3130 /* avoid infinite loop */
3131 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3134 ast *litTree = searchLitOp (tree, &parent, "/");
3137 if (IS_LITERAL (RTYPE (litTree)))
3141 litTree->right = newNode ('*',
3143 copyAst (tree->right));
3144 litTree->right->filename = tree->filename;
3145 litTree->right->lineno = tree->lineno;
3147 tree->right->opval.val = constCharVal (1);
3148 decorateType (parent, resultType);
3152 /* litTree->left is literal: no gcse possible.
3153 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3154 this would cause an infinit loop. */
3155 parent->decorated = 1;
3156 decorateType (litTree, resultType);
3163 /*------------------------------------------------------------------*/
3164 /*----------------------------*/
3166 /*----------------------------*/
3168 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3170 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3171 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3172 printTypeChain (LTYPE (tree), stderr);
3173 fprintf (stderr, ",");
3174 printTypeChain (RTYPE (tree), stderr);
3175 fprintf (stderr, "\n");
3176 goto errorTreeReturn;
3178 /* if they are both literal then */
3179 /* rewrite the tree */
3180 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3182 tree->type = EX_VALUE;
3183 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3184 valFromType (RETYPE (tree)));
3185 tree->right = tree->left = NULL;
3186 TETYPE (tree) = getSpec (TTYPE (tree) =
3187 tree->opval.val->type);
3190 LRVAL (tree) = RRVAL (tree) = 1;
3191 TETYPE (tree) = getSpec (TTYPE (tree) =
3192 computeType (LTYPE (tree),
3198 /*------------------------------------------------------------------*/
3199 /*----------------------------*/
3200 /* address dereference */
3201 /*----------------------------*/
3202 case '*': /* can be unary : if right is null then unary operation */
3205 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3207 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3208 goto errorTreeReturn;
3213 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3214 goto errorTreeReturn;
3216 if (IS_ADDRESS_OF_OP(tree->left))
3218 /* replace *&obj with obj */
3219 return tree->left->left;
3221 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3222 TETYPE (tree) = getSpec (TTYPE (tree));
3223 /* adjust the storage class */
3224 switch (DCL_TYPE(tree->left->ftype)) {
3226 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3229 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3232 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3235 SPEC_SCLS (TETYPE (tree)) = 0;
3238 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3241 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3244 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3247 SPEC_SCLS (TETYPE (tree)) = 0;
3256 /*------------------------------------------------------------------*/
3257 /*----------------------------*/
3258 /* multiplication */
3259 /*----------------------------*/
3260 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3262 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3263 goto errorTreeReturn;
3266 /* if they are both literal then */
3267 /* rewrite the tree */
3268 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3270 tree->type = EX_VALUE;
3271 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3272 valFromType (RETYPE (tree)));
3273 tree->right = tree->left = NULL;
3274 TETYPE (tree) = getSpec (TTYPE (tree) =
3275 tree->opval.val->type);
3279 /* if left is a literal exchange left & right */
3280 if (IS_LITERAL (LTYPE (tree)))
3282 ast *tTree = tree->left;
3283 tree->left = tree->right;
3284 tree->right = tTree;
3287 /* if right is a literal and */
3288 /* we can find a 2nd literal in a mul-tree then */
3289 /* rearrange the tree */
3290 if (IS_LITERAL (RTYPE (tree)))
3293 ast *litTree = searchLitOp (tree, &parent, "*");
3297 ast *tTree = litTree->left;
3298 litTree->left = tree->right;
3299 tree->right = tTree;
3300 /* both operands in litTree are literal now */
3301 decorateType (parent, resultType);
3305 LRVAL (tree) = RRVAL (tree) = 1;
3306 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3307 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3308 TETYPE (tree) = getSpec (TTYPE (tree) =
3309 computeType (LTYPE (tree),
3316 /*------------------------------------------------------------------*/
3317 /*----------------------------*/
3318 /* unary '+' operator */
3319 /*----------------------------*/
3324 if (!IS_ARITHMETIC (LTYPE (tree)))
3326 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3327 goto errorTreeReturn;
3330 /* if left is a literal then do it */
3331 if (IS_LITERAL (LTYPE (tree)))
3333 tree->type = EX_VALUE;
3334 tree->opval.val = valFromType (LETYPE (tree));
3336 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3340 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3344 /*------------------------------------------------------------------*/
3345 /*----------------------------*/
3347 /*----------------------------*/
3349 /* this is not a unary operation */
3350 /* if both pointers then problem */
3351 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3352 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3354 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3355 goto errorTreeReturn;
3358 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3359 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3361 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3362 goto errorTreeReturn;
3365 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3366 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3368 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3369 goto errorTreeReturn;
3371 /* if they are both literal then */
3372 /* rewrite the tree */
3373 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3375 tree->type = EX_VALUE;
3376 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3377 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3378 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3379 valFromType (RETYPE (tree)));
3380 tree->right = tree->left = NULL;
3381 TETYPE (tree) = getSpec (TTYPE (tree) =
3382 tree->opval.val->type);
3386 /* if the right is a pointer or left is a literal
3387 xchange left & right */
3388 if (IS_ARRAY (RTYPE (tree)) ||
3389 IS_PTR (RTYPE (tree)) ||
3390 IS_LITERAL (LTYPE (tree)))
3392 ast *tTree = tree->left;
3393 tree->left = tree->right;
3394 tree->right = tTree;
3397 /* if right is a literal and */
3398 /* left is also an addition/subtraction with a literal then */
3399 /* rearrange the tree */
3400 if (IS_LITERAL (RTYPE (tree)))
3402 ast *litTree, *parent;
3403 litTree = searchLitOp (tree, &parent, "+-");
3406 if (litTree->opval.op == '+')
3410 ast *tTree = litTree->left;
3411 litTree->left = tree->right;
3412 tree->right = tree->left;
3415 else if (litTree->opval.op == '-')
3417 if (IS_LITERAL (RTYPE (litTree)))
3421 ast *tTree = litTree->left;
3422 litTree->left = tree->right;
3423 tree->right = tTree;
3429 ast *tTree = litTree->right;
3430 litTree->right = tree->right;
3431 tree->right = tTree;
3432 litTree->opval.op = '+';
3433 tree->opval.op = '-';
3436 decorateType (parent, resultType);
3440 LRVAL (tree) = RRVAL (tree) = 1;
3441 /* if the left is a pointer */
3442 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3443 TETYPE (tree) = getSpec (TTYPE (tree) =
3447 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3448 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3449 TETYPE (tree) = getSpec (TTYPE (tree) =
3450 computeType (LTYPE (tree),
3458 /*------------------------------------------------------------------*/
3459 /*----------------------------*/
3461 /*----------------------------*/
3462 case '-': /* can be unary */
3463 /* if right is null then unary */
3467 if (!IS_ARITHMETIC (LTYPE (tree)))
3469 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3470 goto errorTreeReturn;
3473 /* if left is a literal then do it */
3474 if (IS_LITERAL (LTYPE (tree)))
3476 tree->type = EX_VALUE;
3477 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3479 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3482 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3483 TETYPE (tree) = getSpec (TTYPE (tree) =
3484 computeType (LTYPE (tree),
3492 /*------------------------------------------------------------------*/
3493 /*----------------------------*/
3495 /*----------------------------*/
3497 if (!(IS_PTR (LTYPE (tree)) ||
3498 IS_ARRAY (LTYPE (tree)) ||
3499 IS_ARITHMETIC (LTYPE (tree))))
3501 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3502 goto errorTreeReturn;
3505 if (!(IS_PTR (RTYPE (tree)) ||
3506 IS_ARRAY (RTYPE (tree)) ||
3507 IS_ARITHMETIC (RTYPE (tree))))
3509 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3510 goto errorTreeReturn;
3513 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3514 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3515 IS_INTEGRAL (RTYPE (tree))))
3517 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3518 goto errorTreeReturn;
3521 /* if they are both literal then */
3522 /* rewrite the tree */
3523 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3525 tree->type = EX_VALUE;
3526 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3527 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3528 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3529 valFromType (RETYPE (tree)));
3530 tree->right = tree->left = NULL;
3531 TETYPE (tree) = getSpec (TTYPE (tree) =
3532 tree->opval.val->type);
3536 /* if the left & right are equal then zero */
3537 if (isAstEqual (tree->left, tree->right))
3539 tree->type = EX_VALUE;
3540 tree->left = tree->right = NULL;
3541 tree->opval.val = constCharVal (0);
3542 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3546 /* if both of them are pointers or arrays then */
3547 /* the result is going to be an integer */
3548 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3549 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3550 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3552 /* if only the left is a pointer */
3553 /* then result is a pointer */
3554 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3555 TETYPE (tree) = getSpec (TTYPE (tree) =
3559 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3560 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3562 TETYPE (tree) = getSpec (TTYPE (tree) =
3563 computeType (LTYPE (tree),
3569 LRVAL (tree) = RRVAL (tree) = 1;
3571 /* if right is a literal and */
3572 /* left is also an addition/subtraction with a literal then */
3573 /* rearrange the tree */
3574 if (IS_LITERAL (RTYPE (tree))
3575 /* avoid infinite loop */
3576 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3578 ast *litTree, *litParent;
3579 litTree = searchLitOp (tree, &litParent, "+-");
3582 if (litTree->opval.op == '+')
3586 ast *tTree = litTree->left;
3587 litTree->left = litTree->right;
3588 litTree->right = tree->right;
3589 tree->right = tTree;
3590 tree->opval.op = '+';
3591 litTree->opval.op = '-';
3593 else if (litTree->opval.op == '-')
3595 if (IS_LITERAL (RTYPE (litTree)))
3599 ast *tTree = litTree->left;
3600 litTree->left = tree->right;
3601 tree->right = litParent->left;
3602 litParent->left = tTree;
3603 litTree->opval.op = '+';
3605 tree->decorated = 0;
3606 decorateType (tree, resultType);
3612 ast *tTree = litTree->right;
3613 litTree->right = tree->right;
3614 tree->right = tTree;
3617 decorateType (litParent, resultType);
3622 /*------------------------------------------------------------------*/
3623 /*----------------------------*/
3625 /*----------------------------*/
3627 /* can be only integral type */
3628 if (!IS_INTEGRAL (LTYPE (tree)))
3630 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3631 goto errorTreeReturn;
3634 /* if left is a literal then do it */
3635 if (IS_LITERAL (LTYPE (tree)))
3637 tree->type = EX_VALUE;
3638 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3640 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3641 return addCast (tree, resultTypeProp, TRUE);
3644 if (resultType == RESULT_TYPE_BIT &&
3645 IS_UNSIGNED (tree->left->etype) &&
3646 getSize (tree->left->etype) < INTSIZE)
3648 /* promotion rules are responsible for this strange result:
3649 bit -> int -> ~int -> bit
3650 uchar -> int -> ~int -> bit
3652 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3654 /* optimize bit-result, even if we optimize a buggy source */
3655 tree->type = EX_VALUE;
3656 tree->opval.val = constCharVal (1);
3659 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3661 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3664 /*------------------------------------------------------------------*/
3665 /*----------------------------*/
3667 /*----------------------------*/
3669 /* can be pointer */
3670 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3671 !IS_PTR (LTYPE (tree)) &&
3672 !IS_ARRAY (LTYPE (tree)))
3674 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3675 goto errorTreeReturn;
3678 /* if left is another '!' */
3679 if (IS_AST_NOT_OPER (tree->left))
3681 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3683 /* replace double '!!X' by 'X' */
3684 return tree->left->left;
3686 /* remove double '!!X' by 'X ? 1 : 0' */
3687 tree->opval.op = '?';
3688 tree->left = tree->left->left;
3689 tree->right = newNode (':',
3690 newAst_VALUE (constCharVal (1)),
3691 newAst_VALUE (constCharVal (0)));
3692 tree->right->filename = tree->filename;
3693 tree->right->lineno = tree->lineno;
3694 tree->decorated = 0;
3695 return decorateType (tree, resultType);
3698 /* if left is a literal then do it */
3699 if (IS_LITERAL (LTYPE (tree)))
3701 tree->type = EX_VALUE;
3702 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3704 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3708 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3711 /*------------------------------------------------------------------*/
3712 /*----------------------------*/
3714 /*----------------------------*/
3718 TTYPE (tree) = LTYPE (tree);
3719 TETYPE (tree) = LETYPE (tree);
3724 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3728 TTYPE (tree) = TETYPE (tree) = newCharLink();
3732 TTYPE (tree) = TETYPE (tree) = newIntLink();
3737 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3739 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3740 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3741 printTypeChain (LTYPE (tree), stderr);
3742 fprintf (stderr, ",");
3743 printTypeChain (RTYPE (tree), stderr);
3744 fprintf (stderr, "\n");
3745 goto errorTreeReturn;
3748 /* make smaller type only if it's a LEFT_OP */
3749 if (tree->opval.op == LEFT_OP)
3750 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3752 /* if they are both literal then */
3753 /* rewrite the tree */
3754 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3756 tree->type = EX_VALUE;
3757 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3758 valFromType (RETYPE (tree)),
3759 (tree->opval.op == LEFT_OP ? 1 : 0));
3760 tree->right = tree->left = NULL;
3761 TETYPE (tree) = getSpec (TTYPE (tree) =
3762 tree->opval.val->type);
3766 /* see if this is a GETBYTE operation if yes
3769 ast *otree = optimizeGetByte (tree, resultType);
3772 return decorateType (otree, RESULT_TYPE_NONE);
3775 /* see if this is a GETWORD operation if yes
3778 ast *otree = optimizeGetWord (tree, resultType);
3781 return decorateType (otree, RESULT_TYPE_NONE);
3784 LRVAL (tree) = RRVAL (tree) = 1;
3785 if (tree->opval.op == LEFT_OP)
3787 TETYPE (tree) = getSpec (TTYPE (tree) =
3788 computeType (LTYPE (tree),
3795 /* no promotion necessary */
3796 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3797 if (IS_LITERAL (TTYPE (tree)))
3798 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3801 /* if only the right side is a literal & we are
3802 shifting more than size of the left operand then zero */
3803 if (IS_LITERAL (RTYPE (tree)) &&
3804 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3805 (getSize (TETYPE (tree)) * 8))
3807 if (tree->opval.op==LEFT_OP ||
3808 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3810 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3811 (tree->opval.op == LEFT_OP ? "left" : "right"));
3812 tree->type = EX_VALUE;
3813 tree->left = tree->right = NULL;
3814 tree->opval.val = constCharVal (0);
3815 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3822 /*------------------------------------------------------------------*/
3823 /*----------------------------*/
3825 /*----------------------------*/
3826 case CAST: /* change the type */
3827 /* cannot cast to an aggregate type */
3828 if (IS_AGGREGATE (LTYPE (tree)))
3830 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3831 goto errorTreeReturn;
3834 /* make sure the type is complete and sane */
3835 changePointer(LTYPE(tree));
3836 checkTypeSanity(LETYPE(tree), "(cast)");
3839 /* if 'from' and 'to' are the same remove the superfluous cast,
3840 * this helps other optimizations */
3841 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3843 /* mark that the explicit cast has been removed,
3844 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3845 tree->right->values.removedCast = 1;
3849 /* If code memory is read only, then pointers to code memory */
3850 /* implicitly point to constants -- make this explicit */
3852 sym_link *t = LTYPE(tree);
3853 while (t && t->next)
3855 if (IS_CODEPTR(t) && port->mem.code_ro)
3857 if (IS_SPEC(t->next))
3858 SPEC_CONST (t->next) = 1;
3860 DCL_PTR_CONST (t->next) = 1;
3867 /* if the right is a literal replace the tree */
3868 if (IS_LITERAL (RETYPE (tree))) {
3869 if (!IS_PTR (LTYPE (tree))) {
3870 tree->type = EX_VALUE;
3872 valCastLiteral (LTYPE (tree),
3873 floatFromVal (valFromType (RETYPE (tree))));
3876 TTYPE (tree) = tree->opval.val->type;
3877 tree->values.literalFromCast = 1;
3878 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3879 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3880 sym_link *rest = LTYPE(tree)->next;
3881 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3882 TTYPE(tree) = newLink(DECLARATOR);
3883 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3884 TTYPE(tree)->next = rest;
3885 tree->left->opval.lnk = TTYPE(tree);
3888 TTYPE (tree) = LTYPE (tree);
3892 TTYPE (tree) = LTYPE (tree);
3896 #if 0 // this is already checked, now this could be explicit
3897 /* if pointer to struct then check names */
3898 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3899 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3900 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3902 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3903 SPEC_STRUCT(LETYPE(tree))->tag);
3906 if (IS_ADDRESS_OF_OP(tree->right)
3907 && IS_AST_SYM_VALUE (tree->right->left)
3908 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3910 symbol * sym = AST_SYMBOL (tree->right->left);
3911 unsigned int gptype = 0;
3912 unsigned int addr = SPEC_ADDR (sym->etype);
3914 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3915 || TARGET_IS_PIC16) )
3917 switch (SPEC_SCLS (sym->etype))
3920 gptype = GPTYPE_CODE;
3923 gptype = GPTYPE_FAR;
3927 gptype = GPTYPE_NEAR;
3930 gptype = GPTYPE_XSTACK;
3935 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3936 gptype = GPTYPE_NEAR;
3938 addr |= gptype << (8*(GPTRSIZE - 1));
3941 tree->type = EX_VALUE;
3943 valCastLiteral (LTYPE (tree), addr);
3944 TTYPE (tree) = tree->opval.val->type;
3945 TETYPE (tree) = getSpec (TTYPE (tree));
3948 tree->values.literalFromCast = 1;
3952 /* handle offsetof macro: */
3953 /* #define offsetof(TYPE, MEMBER) \ */
3954 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3955 if (IS_ADDRESS_OF_OP(tree->right)
3956 && IS_AST_OP (tree->right->left)
3957 && tree->right->left->opval.op == PTR_OP
3958 && IS_AST_OP (tree->right->left->left)
3959 && tree->right->left->left->opval.op == CAST
3960 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3962 symbol *element = getStructElement (
3963 SPEC_STRUCT (LETYPE(tree->right->left)),
3964 AST_SYMBOL(tree->right->left->right)
3968 tree->type = EX_VALUE;
3969 tree->opval.val = valCastLiteral (
3972 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3975 TTYPE (tree) = tree->opval.val->type;
3976 TETYPE (tree) = getSpec (TTYPE (tree));
3983 /* if the right is a literal replace the tree */
3984 if (IS_LITERAL (RETYPE (tree))) {
3986 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3987 /* rewrite (type *)litaddr
3989 and define type at litaddr temp
3990 (but only if type's storage class is not generic)
3992 ast *newTree = newNode ('&', NULL, NULL);
3995 TTYPE (newTree) = LTYPE (tree);
3996 TETYPE (newTree) = getSpec(LTYPE (tree));
3998 /* define a global symbol at the casted address*/
3999 sym = newSymbol(genSymName (0), 0);
4000 sym->type = LTYPE (tree)->next;
4002 sym->type = newLink (V_VOID);
4003 sym->etype = getSpec(sym->type);
4004 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4005 sym->lineDef = tree->lineno;
4008 SPEC_STAT (sym->etype) = 1;
4009 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4010 SPEC_ABSA(sym->etype) = 1;
4011 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4014 newTree->left = newAst_VALUE(symbolVal(sym));
4015 newTree->left->filename = tree->filename;
4016 newTree->left->lineno = tree->lineno;
4017 LTYPE (newTree) = sym->type;
4018 LETYPE (newTree) = sym->etype;
4019 LLVAL (newTree) = 1;
4020 LRVAL (newTree) = 0;
4021 TLVAL (newTree) = 1;
4025 if (!IS_PTR (LTYPE (tree))) {
4026 tree->type = EX_VALUE;
4028 valCastLiteral (LTYPE (tree),
4029 floatFromVal (valFromType (RTYPE (tree))));
4030 TTYPE (tree) = tree->opval.val->type;
4033 tree->values.literalFromCast = 1;
4034 TETYPE (tree) = getSpec (TTYPE (tree));
4038 TTYPE (tree) = LTYPE (tree);
4042 TETYPE (tree) = getSpec (TTYPE (tree));
4046 /*------------------------------------------------------------------*/
4047 /*----------------------------*/
4048 /* logical &&, || */
4049 /*----------------------------*/
4052 /* each must be arithmetic type or be a pointer */
4053 if (!IS_PTR (LTYPE (tree)) &&
4054 !IS_ARRAY (LTYPE (tree)) &&
4055 !IS_INTEGRAL (LTYPE (tree)))
4057 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4058 goto errorTreeReturn;
4061 if (!IS_PTR (RTYPE (tree)) &&
4062 !IS_ARRAY (RTYPE (tree)) &&
4063 !IS_INTEGRAL (RTYPE (tree)))
4065 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4066 goto errorTreeReturn;
4068 /* if they are both literal then */
4069 /* rewrite the tree */
4070 if (IS_LITERAL (RTYPE (tree)) &&
4071 IS_LITERAL (LTYPE (tree)))
4073 tree->type = EX_VALUE;
4074 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4075 valFromType (RTYPE (tree)),
4077 tree->right = tree->left = NULL;
4078 TETYPE (tree) = getSpec (TTYPE (tree) =
4079 tree->opval.val->type);
4082 LRVAL (tree) = RRVAL (tree) = 1;
4083 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4086 /*------------------------------------------------------------------*/
4087 /*----------------------------*/
4088 /* comparison operators */
4089 /*----------------------------*/
4097 ast *lt = optimizeCompare (tree);
4103 /* if they are pointers they must be castable */
4104 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4106 if (tree->opval.op==EQ_OP &&
4107 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4108 // we cannot cast a gptr to a !gptr: switch the leaves
4109 struct ast *s=tree->left;
4110 tree->left=tree->right;
4113 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4115 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4116 fprintf (stderr, "comparing type ");
4117 printTypeChain (LTYPE (tree), stderr);
4118 fprintf (stderr, "to type ");
4119 printTypeChain (RTYPE (tree), stderr);
4120 fprintf (stderr, "\n");
4121 goto errorTreeReturn;
4124 /* else they should be promotable to one another */
4127 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4128 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4130 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4132 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4133 fprintf (stderr, "comparing type ");
4134 printTypeChain (LTYPE (tree), stderr);
4135 fprintf (stderr, "to type ");
4136 printTypeChain (RTYPE (tree), stderr);
4137 fprintf (stderr, "\n");
4138 goto errorTreeReturn;
4143 CCR_RESULT ccr_result = CCR_OK;
4145 /* if left is integral and right is literal
4146 then check constant range */
4147 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4148 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4149 tree->opval.op, FALSE);
4150 if (ccr_result == CCR_OK &&
4151 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4152 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4153 tree->opval.op, TRUE);
4156 case CCR_ALWAYS_TRUE:
4157 case CCR_ALWAYS_FALSE:
4158 if (!options.lessPedantic)
4159 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4160 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4161 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4168 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4169 if (tree->opval.op == '>' &&
4170 SPEC_USIGN(LETYPE(tree)) &&
4171 IS_LITERAL(RTYPE(tree)) &&
4172 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4174 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4176 /* the parent is an ifx: */
4177 /* if (unsigned value) */
4181 /* (unsigned value) ? 1 : 0 */
4182 tree->opval.op = '?';
4183 tree->right = newNode (':',
4184 newAst_VALUE (constCharVal (1)),
4185 tree->right); /* val 0 */
4186 tree->right->filename = tree->filename;
4187 tree->right->lineno = tree->lineno;
4188 tree->right->left->filename = tree->filename;
4189 tree->right->left->lineno = tree->lineno;
4190 tree->decorated = 0;
4191 return decorateType (tree, resultType);
4194 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4195 if (IS_LITERAL(RTYPE(tree)) &&
4196 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4197 tree->opval.op == EQ_OP &&
4198 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4200 tree->opval.op = '!';
4202 tree->decorated = 0;
4203 return decorateType (tree, resultType);
4206 /* if they are both literal then */
4207 /* rewrite the tree */
4208 if (IS_LITERAL (RTYPE (tree)) &&
4209 IS_LITERAL (LTYPE (tree)))
4211 tree->type = EX_VALUE;
4212 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4213 valFromType (RETYPE (tree)),
4215 tree->right = tree->left = NULL;
4216 TETYPE (tree) = getSpec (TTYPE (tree) =
4217 tree->opval.val->type);
4221 /* if one is 'signed char ' and the other one is 'unsigned char' */
4222 /* it's necessary to promote to int */
4223 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4224 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4226 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4227 if it's possible to use a 'signed char' */
4229 /* is left a 'unsigned char'? */
4230 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4231 /* the value range of a 'unsigned char' is 0...255;
4232 if the actual value is < 128 it can be changed to signed */
4233 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4235 /* now we've got 2 'signed char'! */
4236 SPEC_USIGN (RETYPE (tree)) = 0;
4238 /* same test for the left operand: */
4239 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4240 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4242 SPEC_USIGN (LETYPE (tree)) = 0;
4246 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4247 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4248 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4252 LRVAL (tree) = RRVAL (tree) = 1;
4253 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4255 /* condition transformations */
4257 unsigned transformedOp = 0;
4259 switch (tree->opval.op)
4261 case '<': /* transform (a < b) to !(a >= b) */
4263 transformedOp = GE_OP;
4265 case '>': /* transform (a > b) to !(a <= b) */
4267 transformedOp = LE_OP;
4269 case LE_OP: /* transform (a <= b) to !(a > b) */
4271 transformedOp = '>';
4273 case GE_OP: /* transform (a >= b) to !(a < b) */
4275 transformedOp = '<';
4277 case NE_OP: /* transform (a != b) to !(a == b) */
4279 transformedOp = EQ_OP;
4281 case EQ_OP: /* transform (a == b) to !(a != b) */
4283 transformedOp = NE_OP;
4290 tree->opval.op = transformedOp;
4291 tree->decorated = 0;
4292 tree = newNode ('!', tree, NULL);
4293 tree->filename = tree->left->filename;
4294 tree->lineno = tree->left->lineno;
4295 return decorateType (tree, resultType);
4301 /*------------------------------------------------------------------*/
4302 /*----------------------------*/
4304 /*----------------------------*/
4305 case SIZEOF: /* evaluate wihout code generation */
4306 /* change the type to a integer */
4308 int size = getSize (tree->right->ftype);
4310 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4311 if (!size && !IS_VOID(tree->right->ftype))
4312 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4314 tree->type = EX_VALUE;
4315 tree->opval.val = constVal (buffer);
4316 tree->right = tree->left = NULL;
4317 TETYPE (tree) = getSpec (TTYPE (tree) =
4318 tree->opval.val->type);
4322 /*------------------------------------------------------------------*/
4323 /*----------------------------*/
4325 /*----------------------------*/
4327 /* return typeof enum value */
4328 tree->type = EX_VALUE;
4331 if (IS_SPEC(tree->right->ftype)) {
4332 switch (SPEC_NOUN(tree->right->ftype)) {
4334 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4335 else typeofv = TYPEOF_INT;
4338 typeofv = TYPEOF_FLOAT;
4341 typeofv = TYPEOF_FIXED16X16;
4344 typeofv = TYPEOF_CHAR;
4347 typeofv = TYPEOF_VOID;
4350 typeofv = TYPEOF_STRUCT;
4353 typeofv = TYPEOF_BITFIELD;
4356 typeofv = TYPEOF_BIT;
4359 typeofv = TYPEOF_SBIT;
4365 switch (DCL_TYPE(tree->right->ftype)) {
4367 typeofv = TYPEOF_POINTER;
4370 typeofv = TYPEOF_FPOINTER;
4373 typeofv = TYPEOF_CPOINTER;
4376 typeofv = TYPEOF_GPOINTER;
4379 typeofv = TYPEOF_PPOINTER;
4382 typeofv = TYPEOF_IPOINTER;
4385 typeofv = TYPEOF_ARRAY;
4388 typeofv = TYPEOF_FUNCTION;
4394 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4395 tree->opval.val = constVal (buffer);
4396 tree->right = tree->left = NULL;
4397 TETYPE (tree) = getSpec (TTYPE (tree) =
4398 tree->opval.val->type);
4401 /*------------------------------------------------------------------*/
4402 /*----------------------------*/
4403 /* conditional operator '?' */
4404 /*----------------------------*/
4406 /* the type is value of the colon operator (on the right) */
4407 assert (IS_COLON_OP (tree->right));
4409 /* If already known then replace the tree : optimizer will do it
4410 but faster to do it here. If done before decorating tree->right
4411 this can save generating unused const strings. */
4412 if (IS_LITERAL (LTYPE (tree)))
4414 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4415 return decorateType (tree->right->left, resultTypeProp);
4417 return decorateType (tree->right->right, resultTypeProp);
4420 tree->right = decorateType (tree->right, resultTypeProp);
4422 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4423 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4425 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4426 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4428 if ((valTrue != 0) && (valFalse == 0))
4430 /* assign cond to result */
4431 tree->left->decorated = 0;
4432 return decorateType (tree->left, resultTypeProp);
4434 else if ((valTrue == 0) && (valFalse != 0))
4436 /* assign !cond to result */
4437 tree->opval.op = '!';
4438 tree->decorated = 0;
4440 return decorateType (tree, resultTypeProp);
4444 /* they have the same boolean value, make them equal */
4445 tree->right->left = tree->right->right;
4449 /* if they are equal then replace the tree */
4450 if (isAstEqual (tree->right->left, tree->right->right))
4452 return tree->right->left;
4455 TTYPE (tree) = RTYPE (tree);
4456 TETYPE (tree) = getSpec (TTYPE (tree));
4460 /* if they don't match we have a problem */
4461 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4462 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4464 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4465 goto errorTreeReturn;
4468 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4469 resultType, tree->opval.op);
4470 TETYPE (tree) = getSpec (TTYPE (tree));
4474 #if 0 // assignment operators are converted by the parser
4475 /*------------------------------------------------------------------*/
4476 /*----------------------------*/
4477 /* assignment operators */
4478 /*----------------------------*/
4481 /* for these it must be both must be integral */
4482 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4483 !IS_ARITHMETIC (RTYPE (tree)))
4485 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4486 goto errorTreeReturn;
4489 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4491 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4492 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4496 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4497 goto errorTreeReturn;
4508 /* for these it must be both must be integral */
4509 if (!IS_INTEGRAL (LTYPE (tree)) ||
4510 !IS_INTEGRAL (RTYPE (tree)))
4512 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4513 goto errorTreeReturn;
4516 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4518 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4519 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4523 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4524 goto errorTreeReturn;
4530 /*------------------------------------------------------------------*/
4531 /*----------------------------*/
4533 /*----------------------------*/
4535 if (!(IS_PTR (LTYPE (tree)) ||
4536 IS_ARITHMETIC (LTYPE (tree))))
4538 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4539 goto errorTreeReturn;
4542 if (!(IS_PTR (RTYPE (tree)) ||
4543 IS_ARITHMETIC (RTYPE (tree))))
4545 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4546 goto errorTreeReturn;
4549 TETYPE (tree) = getSpec (TTYPE (tree) =
4550 computeType (LTYPE (tree),
4555 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4556 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4560 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4561 goto errorTreeReturn;
4567 /*------------------------------------------------------------------*/
4568 /*----------------------------*/
4570 /*----------------------------*/
4572 /* this is not a unary operation */
4573 /* if both pointers then problem */
4574 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4576 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4577 goto errorTreeReturn;
4580 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4582 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4583 goto errorTreeReturn;
4586 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4588 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4589 goto errorTreeReturn;
4592 TETYPE (tree) = getSpec (TTYPE (tree) =
4593 computeType (LTYPE (tree),
4598 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4599 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4603 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4604 goto errorTreeReturn;
4607 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4608 tree->opval.op = '=';
4613 /*------------------------------------------------------------------*/
4614 /*----------------------------*/
4615 /* straight assignemnt */
4616 /*----------------------------*/
4618 /* cannot be an aggregate */
4619 if (IS_AGGREGATE (LTYPE (tree)))
4621 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4622 goto errorTreeReturn;
4625 /* they should either match or be castable */
4626 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4628 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4629 printFromToType(RTYPE(tree),LTYPE(tree));
4632 /* if the left side of the tree is of type void
4633 then report error */
4634 if (IS_VOID (LTYPE (tree)))
4636 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4637 printFromToType(RTYPE(tree), LTYPE(tree));
4640 TETYPE (tree) = getSpec (TTYPE (tree) =
4644 if (!tree->initMode ) {
4645 if (IS_CONSTANT(LTYPE(tree)))
4646 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4650 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4651 goto errorTreeReturn;
4656 /*------------------------------------------------------------------*/
4657 /*----------------------------*/
4658 /* comma operator */
4659 /*----------------------------*/
4661 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4664 /*------------------------------------------------------------------*/
4665 /*----------------------------*/
4667 /*----------------------------*/
4670 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4671 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4673 if (tree->left->opval.op == '*' && !tree->left->right)
4674 tree->left = tree->left->left;
4677 /* require a function or pointer to function */
4678 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4680 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4681 goto errorTreeReturn;
4684 /* if there are parms, make sure that
4685 parms are decorate / process / reverse only once */
4687 !tree->right->decorated)
4692 if (IS_FUNCPTR (LTYPE (tree)))
4694 functype = LTYPE (tree)->next;
4695 processFuncPtrArgs (functype);
4698 functype = LTYPE (tree);
4700 if (processParms (tree->left, FUNC_ARGS(functype),
4701 &tree->right, &parmNumber, TRUE))
4703 goto errorTreeReturn;
4706 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4707 !IFFUNC_ISBUILTIN(functype))
4709 reverseParms (tree->right);
4712 TTYPE (tree) = functype->next;
4713 TETYPE (tree) = getSpec (TTYPE (tree));
4717 /*------------------------------------------------------------------*/
4718 /*----------------------------*/
4719 /* return statement */
4720 /*----------------------------*/
4725 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4727 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4728 printFromToType (RTYPE(tree), currFunc->type->next);
4729 goto errorTreeReturn;
4732 if (IS_VOID (currFunc->type->next)
4734 !IS_VOID (RTYPE (tree)))
4736 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4737 goto errorTreeReturn;
4740 /* if there is going to be a casting required then add it */
4741 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4744 decorateType (newNode (CAST,
4745 newAst_LINK (copyLinkChain (currFunc->type->next)),
4755 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4757 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4758 goto errorTreeReturn;
4761 TTYPE (tree) = TETYPE (tree) = NULL;
4764 /*------------------------------------------------------------------*/
4765 /*----------------------------*/
4766 /* switch statement */
4767 /*----------------------------*/
4769 /* the switch value must be an integer */
4770 if (!IS_INTEGRAL (LTYPE (tree)))
4772 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4773 goto errorTreeReturn;
4776 TTYPE (tree) = TETYPE (tree) = NULL;
4779 /*------------------------------------------------------------------*/
4780 /*----------------------------*/
4782 /*----------------------------*/
4784 tree->left = backPatchLabels (tree->left,
4787 TTYPE (tree) = TETYPE (tree) = NULL;
4790 /*------------------------------------------------------------------*/
4791 /*----------------------------*/
4793 /*----------------------------*/
4796 AST_FOR (tree, initExpr) = decorateType (
4797 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4798 AST_FOR (tree, condExpr) = decorateType (
4799 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4800 AST_FOR (tree, loopExpr) = decorateType (
4801 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4803 /* if the for loop is reversible then
4804 reverse it otherwise do what we normally
4810 if (isLoopReversible (tree, &sym, &init, &end))
4811 return reverseLoop (tree, sym, init, end);
4813 return decorateType (createFor (AST_FOR (tree, trueLabel),
4814 AST_FOR (tree, continueLabel),
4815 AST_FOR (tree, falseLabel),
4816 AST_FOR (tree, condLabel),
4817 AST_FOR (tree, initExpr),
4818 AST_FOR (tree, condExpr),
4819 AST_FOR (tree, loopExpr),
4820 tree->left), RESULT_TYPE_NONE);
4823 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4824 "node PARAM shouldn't be processed here");
4825 /* but in processParams() */
4828 TTYPE (tree) = TETYPE (tree) = NULL;
4832 /* some error found this tree will be killed */
4834 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4835 tree->opval.op = NULLOP;
4841 /*-----------------------------------------------------------------*/
4842 /* sizeofOp - processes size of operation */
4843 /*-----------------------------------------------------------------*/
4845 sizeofOp (sym_link * type)
4850 /* make sure the type is complete and sane */
4851 checkTypeSanity(type, "(sizeof)");
4853 /* get the size and convert it to character */
4854 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4855 if (!size && !IS_VOID(type))
4856 werror (E_SIZEOF_INCOMPLETE_TYPE);
4858 /* now convert into value */
4859 return constVal (buff);
4863 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4864 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4865 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4866 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4867 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4868 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4869 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4871 /*-----------------------------------------------------------------*/
4872 /* backPatchLabels - change and or not operators to flow control */
4873 /*-----------------------------------------------------------------*/
4875 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4881 /* while-loops insert a label between the IFX and the condition,
4882 therefore look behind the label too */
4883 if (tree->opval.op == LABEL &&
4885 IS_ANDORNOT (tree->right))
4887 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4891 if (!(IS_ANDORNOT (tree)))
4894 /* if this an and */
4897 static int localLbl = 0;
4900 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4901 localLabel = newSymbol (buffer, NestLevel);
4903 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4905 /* if left is already a IFX then just change the if true label in that */
4906 if (!IS_IFX (tree->left))
4907 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4909 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4910 /* right is a IFX then just join */
4911 if (IS_IFX (tree->right))
4912 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4914 tree->right = createLabel (localLabel, tree->right);
4915 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4917 return newNode (NULLOP, tree->left, tree->right);
4920 /* if this is an or operation */
4923 static int localLbl = 0;
4926 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4927 localLabel = newSymbol (buffer, NestLevel);
4929 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4931 /* if left is already a IFX then just change the if true label in that */
4932 if (!IS_IFX (tree->left))
4933 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4935 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4936 /* right is a IFX then just join */
4937 if (IS_IFX (tree->right))
4938 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4940 tree->right = createLabel (localLabel, tree->right);
4941 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4943 return newNode (NULLOP, tree->left, tree->right);
4949 /* call with exchanged labels */
4950 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4952 /* if left isn't already a IFX */
4953 if (!IS_IFX (tree->left))
4955 tree->left = newNode (IFX, tree->left, NULL);
4956 tree->left->trueLabel = falseLabel;
4957 tree->left->falseLabel = trueLabel;
4964 tree->trueLabel = trueLabel;
4965 tree->falseLabel = falseLabel;
4972 /*-----------------------------------------------------------------*/
4973 /* createBlock - create expression tree for block */
4974 /*-----------------------------------------------------------------*/
4976 createBlock (symbol * decl, ast * body)
4980 /* if the block has nothing */
4984 ex = newNode (BLOCK, NULL, body);
4985 ex->values.sym = decl;
4988 ex->filename = NULL;
4993 /*-----------------------------------------------------------------*/
4994 /* createLabel - creates the expression tree for labels */
4995 /*-----------------------------------------------------------------*/
4997 createLabel (symbol * label, ast * stmnt)
5000 char name[SDCC_NAME_MAX + 1];
5003 /* must create fresh symbol if the symbol name */
5004 /* exists in the symbol table, since there can */
5005 /* be a variable with the same name as the labl */
5006 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5007 (csym->level == label->level))
5008 label = newSymbol (label->name, label->level);
5010 /* change the name before putting it in add _ */
5011 SNPRINTF(name, sizeof(name), "%s", label->name);
5013 /* put the label in the LabelSymbol table */
5014 /* but first check if a label of the same */
5016 if ((csym = findSym (LabelTab, NULL, name)))
5017 werror (E_DUPLICATE_LABEL, label->name);
5019 addSym (LabelTab, label, name, label->level, 0, 0);
5023 label->key = labelKey++;
5024 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5025 rValue->filename = NULL;
5031 /*-----------------------------------------------------------------*/
5032 /* createCase - generates the parsetree for a case statement */
5033 /*-----------------------------------------------------------------*/
5035 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5037 char caseLbl[SDCC_NAME_MAX + 1];
5041 /* if the switch statement does not exist */
5042 /* then case is out of context */
5045 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5049 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5050 /* if not a constant then error */
5051 if (!IS_LITERAL (caseVal->ftype))
5053 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5057 /* if not a integer than error */
5058 if (!IS_INTEGRAL (caseVal->ftype))
5060 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5064 /* find the end of the switch values chain */
5065 if (!(val = swStat->values.switchVals.swVals))
5066 swStat->values.switchVals.swVals = caseVal->opval.val;
5069 /* also order the cases according to value */
5071 int cVal = (int) ulFromVal (caseVal->opval.val);
5072 while (val && (int) ulFromVal (val) < cVal)
5078 /* if we reached the end then */
5081 pval->next = caseVal->opval.val;
5083 else if ((int) ulFromVal (val) == cVal)
5085 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5091 /* we found a value greater than */
5092 /* the current value we must add this */
5093 /* before the value */
5094 caseVal->opval.val->next = val;
5096 /* if this was the first in chain */
5097 if (swStat->values.switchVals.swVals == val)
5098 swStat->values.switchVals.swVals =
5101 pval->next = caseVal->opval.val;
5106 /* create the case label */
5107 SNPRINTF(caseLbl, sizeof(caseLbl),
5109 swStat->values.switchVals.swNum,
5110 (int) ulFromVal (caseVal->opval.val));
5112 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5113 rexpr->filename = 0;
5118 /*-----------------------------------------------------------------*/
5119 /* createDefault - creates the parse tree for the default statement */
5120 /*-----------------------------------------------------------------*/
5122 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5124 char defLbl[SDCC_NAME_MAX + 1];
5126 /* if the switch statement does not exist */
5127 /* then case is out of context */
5130 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5134 if (swStat->values.switchVals.swDefault)
5136 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5141 /* turn on the default flag */
5142 swStat->values.switchVals.swDefault = 1;
5144 /* create the label */
5145 SNPRINTF (defLbl, sizeof(defLbl),
5146 "_default_%d", swStat->values.switchVals.swNum);
5147 return createLabel (newSymbol (defLbl, 0), stmnt);
5150 /*-----------------------------------------------------------------*/
5151 /* createIf - creates the parsetree for the if statement */
5152 /*-----------------------------------------------------------------*/
5154 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5156 static int Lblnum = 0;
5158 symbol *ifTrue, *ifFalse, *ifEnd;
5160 /* if neither exists */
5161 if (!elseBody && !ifBody) {
5162 // if there are no side effects (i++, j() etc)
5163 if (!hasSEFcalls(condAst)) {
5168 /* create the labels */
5169 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5170 ifFalse = newSymbol (buffer, NestLevel);
5171 /* if no else body then end == false */
5176 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5177 ifEnd = newSymbol (buffer, NestLevel);
5180 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5181 ifTrue = newSymbol (buffer, NestLevel);
5185 /* attach the ifTrue label to the top of it body */
5186 ifBody = createLabel (ifTrue, ifBody);
5187 /* attach a goto end to the ifBody if else is present */
5190 ifBody = newNode (NULLOP, ifBody,
5192 newAst_VALUE (symbolVal (ifEnd)),
5194 /* put the elseLabel on the else body */
5195 elseBody = createLabel (ifFalse, elseBody);
5196 /* out the end at the end of the body */
5197 elseBody = newNode (NULLOP,
5199 createLabel (ifEnd, NULL));
5203 ifBody = newNode (NULLOP, ifBody,
5204 createLabel (ifFalse, NULL));
5206 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5207 if (IS_IFX (condAst))
5210 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5212 return newNode (NULLOP, ifTree,
5213 newNode (NULLOP, ifBody, elseBody));
5217 /*-----------------------------------------------------------------*/
5218 /* createDo - creates parse tree for do */
5221 /* _docontinue_n: */
5222 /* condition_expression +-> trueLabel -> _dobody_n */
5224 /* +-> falseLabel-> _dobreak_n */
5226 /*-----------------------------------------------------------------*/
5228 createDo (symbol * trueLabel, symbol * continueLabel,
5229 symbol * falseLabel, ast * condAst, ast * doBody)
5234 /* if the body does not exist then it is simple */
5237 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5238 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5239 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5240 doTree->trueLabel = continueLabel;
5241 doTree->falseLabel = NULL;
5243 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5247 /* otherwise we have a body */
5248 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5250 /* attach the body label to the top */
5251 doBody = createLabel (trueLabel, doBody);
5252 /* attach the continue label to end of body */
5253 doBody = newNode (NULLOP, doBody,
5254 createLabel (continueLabel, NULL));
5256 /* now put the break label at the end */
5257 if (IS_IFX (condAst))
5260 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5262 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5264 /* putting it together */
5265 return newNode (NULLOP, doBody, doTree);
5268 /*-----------------------------------------------------------------*/
5269 /* createFor - creates parse tree for 'for' statement */
5272 /* condExpr +-> trueLabel -> _forbody_n */
5274 /* +-> falseLabel-> _forbreak_n */
5277 /* _forcontinue_n: */
5279 /* goto _forcond_n ; */
5281 /*-----------------------------------------------------------------*/
5283 createFor (symbol * trueLabel, symbol * continueLabel,
5284 symbol * falseLabel, symbol * condLabel,
5285 ast * initExpr, ast * condExpr, ast * loopExpr,
5290 /* if loopexpression not present then we can generate it */
5291 /* the same way as a while */
5293 return newNode (NULLOP, initExpr,
5294 createWhile (trueLabel, continueLabel,
5295 falseLabel, condExpr, forBody));
5296 /* vanilla for statement */
5297 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5299 if (condExpr && !IS_IFX (condExpr))
5300 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5303 /* attach condition label to condition */
5304 condExpr = createLabel (condLabel, condExpr);
5306 /* attach body label to body */
5307 forBody = createLabel (trueLabel, forBody);
5309 /* attach continue to forLoop expression & attach */
5310 /* goto the forcond @ and of loopExpression */
5311 loopExpr = createLabel (continueLabel,
5315 newAst_VALUE (symbolVal (condLabel)),
5317 /* now start putting them together */
5318 forTree = newNode (NULLOP, initExpr, condExpr);
5319 forTree = newNode (NULLOP, forTree, forBody);
5320 forTree = newNode (NULLOP, forTree, loopExpr);
5321 /* finally add the break label */
5322 forTree = newNode (NULLOP, forTree,
5323 createLabel (falseLabel, NULL));
5327 /*-----------------------------------------------------------------*/
5328 /* createWhile - creates parse tree for while statement */
5329 /* the while statement will be created as follows */
5331 /* _while_continue_n: */
5332 /* condition_expression +-> trueLabel -> _while_boby_n */
5334 /* +-> falseLabel -> _while_break_n */
5335 /* _while_body_n: */
5337 /* goto _while_continue_n */
5338 /* _while_break_n: */
5339 /*-----------------------------------------------------------------*/
5341 createWhile (symbol * trueLabel, symbol * continueLabel,
5342 symbol * falseLabel, ast * condExpr, ast * whileBody)
5346 /* put the continue label */
5347 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5348 condExpr = createLabel (continueLabel, condExpr);
5349 condExpr->filename = NULL;
5350 condExpr->lineno = 0;
5352 /* put the body label in front of the body */
5353 whileBody = createLabel (trueLabel, whileBody);
5354 whileBody->filename = NULL;
5355 whileBody->lineno = 0;
5356 /* put a jump to continue at the end of the body */
5357 /* and put break label at the end of the body */
5358 whileBody = newNode (NULLOP,
5361 newAst_VALUE (symbolVal (continueLabel)),
5362 createLabel (falseLabel, NULL)));
5364 /* put it all together */
5365 if (IS_IFX (condExpr))
5366 whileTree = condExpr;
5369 whileTree = newNode (IFX, condExpr, NULL);
5370 /* put the true & false labels in place */
5371 whileTree->trueLabel = trueLabel;
5372 whileTree->falseLabel = falseLabel;
5375 return newNode (NULLOP, whileTree, whileBody);
5378 /*-----------------------------------------------------------------*/
5379 /* isShiftRightLitVal _BitAndLitVal - helper function */
5380 /*-----------------------------------------------------------------*/
5382 isShiftRightLitVal_BitAndLitVal (ast * tree)
5384 /* if this is not a bit and */
5385 if (!IS_BITAND (tree))
5388 /* will look for tree of the form
5389 ( expr >> litval2) & litval1 */
5390 if (!IS_AST_LIT_VALUE (tree->right))
5393 if (!IS_RIGHT_OP (tree->left))
5396 if (!IS_AST_LIT_VALUE (tree->left->right))
5399 return tree->left->left;
5402 /*-----------------------------------------------------------------*/
5403 /* isBitAndPowOf2 - helper function */
5404 /*-----------------------------------------------------------------*/
5406 isBitAndPow2 (ast * tree)
5408 /* if this is not a bit and */
5409 if (!IS_BITAND (tree))
5412 /* will look for tree of the form
5413 ( expr & (1 << litval) */
5414 if (!IS_AST_LIT_VALUE (tree->right))
5417 return powof2 (AST_ULONG_VALUE (tree->right));
5420 /*-----------------------------------------------------------------*/
5421 /* optimizeGetHbit - get highest order bit of the expression */
5422 /*-----------------------------------------------------------------*/
5424 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5429 expr = isShiftRightLitVal_BitAndLitVal(tree);
5432 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5433 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5434 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5437 if (!expr && (resultType == RESULT_TYPE_BIT))
5440 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5446 /* make sure the port supports GETHBIT */
5447 if (port->hasExtBitOp
5448 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5451 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5454 /*-----------------------------------------------------------------*/
5455 /* optimizeGetAbit - get a single bit of the expression */
5456 /*-----------------------------------------------------------------*/
5458 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5463 expr = isShiftRightLitVal_BitAndLitVal(tree);
5466 if (AST_ULONG_VALUE (tree->right) != 1)
5468 count = tree->left->right;
5470 if (!expr && (resultType == RESULT_TYPE_BIT))
5472 int p2 = isBitAndPow2 (tree);
5476 count = newAst_VALUE (valueFromLit (p2));
5482 /* make sure the port supports GETABIT */
5483 if (port->hasExtBitOp
5484 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5487 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5491 /*-----------------------------------------------------------------*/
5492 /* optimizeGetByte - get a byte of the expression */
5493 /*-----------------------------------------------------------------*/
5495 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5501 expr = isShiftRightLitVal_BitAndLitVal(tree);
5504 i = AST_ULONG_VALUE (tree->left->right);
5505 count = tree->left->right;
5506 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5509 if (!expr && resultType == RESULT_TYPE_CHAR)
5511 /* if this is a right shift over a multiple of 8 */
5512 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5514 i = AST_ULONG_VALUE (tree->right);
5515 count = tree->right;
5519 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5522 /* make sure the port supports GETBYTE */
5523 if (port->hasExtBitOp
5524 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5527 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5530 /*-----------------------------------------------------------------*/
5531 /* optimizeGetWord - get two bytes of the expression */
5532 /*-----------------------------------------------------------------*/
5534 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5540 expr = isShiftRightLitVal_BitAndLitVal(tree);
5543 i = AST_ULONG_VALUE (tree->left->right);
5544 count = tree->left->right;
5545 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5548 if (!expr && resultType == RESULT_TYPE_INT)
5550 /* if this is a right shift over a multiple of 8 */
5551 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5553 i = AST_ULONG_VALUE (tree->right);
5554 count = tree->right;
5558 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5561 /* make sure the port supports GETWORD */
5562 if (port->hasExtBitOp
5563 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5566 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5569 /*-----------------------------------------------------------------*/
5570 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5571 /*-----------------------------------------------------------------*/
5573 optimizeRRCRLC (ast * root)
5575 /* will look for trees of the form
5576 (?expr << 1) | (?expr >> 7) or
5577 (?expr >> 7) | (?expr << 1) will make that
5578 into a RLC : operation ..
5580 (?expr >> 1) | (?expr << 7) or
5581 (?expr << 7) | (?expr >> 1) will make that
5582 into a RRC operation
5583 note : by 7 I mean (number of bits required to hold the
5585 /* if the root operation is not a | operation then not */
5586 if (!IS_BITOR (root))
5589 /* I have to think of a better way to match patterns this sucks */
5590 /* that aside let's start looking for the first case : I use a
5591 negative check a lot to improve the efficiency */
5592 /* (?expr << 1) | (?expr >> 7) */
5593 if (IS_LEFT_OP (root->left) &&
5594 IS_RIGHT_OP (root->right))
5597 if (!SPEC_USIGN (TETYPE (root->left->left)))
5600 if (!IS_AST_LIT_VALUE (root->left->right) ||
5601 !IS_AST_LIT_VALUE (root->right->right))
5604 /* make sure it is the same expression */
5605 if (!isAstEqual (root->left->left,
5609 if (AST_ULONG_VALUE (root->left->right) != 1)
5612 if (AST_ULONG_VALUE (root->right->right) !=
5613 (getSize (TTYPE (root->left->left)) * 8 - 1))
5616 /* make sure the port supports RLC */
5617 if (port->hasExtBitOp
5618 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5621 /* whew got the first case : create the AST */
5622 return newNode (RLC, root->left->left, NULL);
5626 /* check for second case */
5627 /* (?expr >> 7) | (?expr << 1) */
5628 if (IS_LEFT_OP (root->right) &&
5629 IS_RIGHT_OP (root->left))
5632 if (!SPEC_USIGN (TETYPE (root->left->left)))
5635 if (!IS_AST_LIT_VALUE (root->left->right) ||
5636 !IS_AST_LIT_VALUE (root->right->right))
5639 /* make sure it is the same symbol */
5640 if (!isAstEqual (root->left->left,
5644 if (AST_ULONG_VALUE (root->right->right) != 1)
5647 if (AST_ULONG_VALUE (root->left->right) !=
5648 (getSize (TTYPE (root->left->left)) * 8 - 1))
5651 /* make sure the port supports RLC */
5652 if (port->hasExtBitOp
5653 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5656 /* whew got the first case : create the AST */
5657 return newNode (RLC, root->left->left, NULL);
5662 /* third case for RRC */
5663 /* (?symbol >> 1) | (?symbol << 7) */
5664 if (IS_LEFT_OP (root->right) &&
5665 IS_RIGHT_OP (root->left))
5668 if (!SPEC_USIGN (TETYPE (root->left->left)))
5671 if (!IS_AST_LIT_VALUE (root->left->right) ||
5672 !IS_AST_LIT_VALUE (root->right->right))
5675 /* make sure it is the same symbol */
5676 if (!isAstEqual (root->left->left,
5680 if (AST_ULONG_VALUE (root->left->right) != 1)
5683 if (AST_ULONG_VALUE (root->right->right) !=
5684 (getSize (TTYPE (root->left->left)) * 8 - 1))
5687 /* make sure the port supports RRC */
5688 if (port->hasExtBitOp
5689 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5692 /* whew got the first case : create the AST */
5693 return newNode (RRC, root->left->left, NULL);
5697 /* fourth and last case for now */
5698 /* (?symbol << 7) | (?symbol >> 1) */
5699 if (IS_RIGHT_OP (root->right) &&
5700 IS_LEFT_OP (root->left))
5703 if (!SPEC_USIGN (TETYPE (root->left->left)))
5706 if (!IS_AST_LIT_VALUE (root->left->right) ||
5707 !IS_AST_LIT_VALUE (root->right->right))
5710 /* make sure it is the same symbol */
5711 if (!isAstEqual (root->left->left,
5715 if (AST_ULONG_VALUE (root->right->right) != 1)
5718 if (AST_ULONG_VALUE (root->left->right) !=
5719 (getSize (TTYPE (root->left->left)) * 8 - 1))
5722 /* make sure the port supports RRC */
5723 if (port->hasExtBitOp
5724 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5727 /* whew got the first case : create the AST */
5728 return newNode (RRC, root->left->left, NULL);
5732 /* not found return root */
5736 /*-----------------------------------------------------------------*/
5737 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5738 /*-----------------------------------------------------------------*/
5740 optimizeSWAP (ast * root)
5742 /* will look for trees of the form
5743 (?expr << 4) | (?expr >> 4) or
5744 (?expr >> 4) | (?expr << 4) will make that
5745 into a SWAP : operation ..
5746 note : by 4 I mean (number of bits required to hold the
5748 /* if the root operation is not a | operation then not */
5749 if (!IS_BITOR (root))
5752 /* (?expr << 4) | (?expr >> 4) */
5753 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5754 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5757 if (!SPEC_USIGN (TETYPE (root->left->left)))
5760 if (!IS_AST_LIT_VALUE (root->left->right) ||
5761 !IS_AST_LIT_VALUE (root->right->right))
5764 /* make sure it is the same expression */
5765 if (!isAstEqual (root->left->left,
5769 if (AST_ULONG_VALUE (root->left->right) !=
5770 (getSize (TTYPE (root->left->left)) * 4))
5773 if (AST_ULONG_VALUE (root->right->right) !=
5774 (getSize (TTYPE (root->left->left)) * 4))
5777 /* make sure the port supports SWAP */
5778 if (port->hasExtBitOp
5779 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5782 /* found it : create the AST */
5783 return newNode (SWAP, root->left->left, NULL);
5787 /* not found return root */
5791 /*-----------------------------------------------------------------*/
5792 /* optimizeCompare - optimizes compares for bit variables */
5793 /*-----------------------------------------------------------------*/
5795 optimizeCompare (ast * root)
5797 ast *optExpr = NULL;
5800 unsigned int litValue;
5802 /* if nothing then return nothing */
5806 /* if not a compare op then do leaves */
5807 if (!IS_COMPARE_OP (root))
5809 root->left = optimizeCompare (root->left);
5810 root->right = optimizeCompare (root->right);
5814 /* if left & right are the same then depending
5815 of the operation do */
5816 if (isAstEqual (root->left, root->right))
5818 switch (root->opval.op)
5823 optExpr = newAst_VALUE (constCharVal (0));
5828 optExpr = newAst_VALUE (constCharVal (1));
5832 return decorateType (optExpr, RESULT_TYPE_NONE);
5835 vleft = (root->left->type == EX_VALUE ?
5836 root->left->opval.val : NULL);
5838 vright = (root->right->type == EX_VALUE ?
5839 root->right->opval.val : NULL);
5841 /* if left is a BITVAR in BITSPACE */
5842 /* and right is a LITERAL then */
5843 /* optimize else do nothing */
5844 if (vleft && vright &&
5845 IS_BITVAR (vleft->etype) &&
5846 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5847 IS_LITERAL (vright->etype))
5850 /* if right side > 1 then comparison may never succeed */
5851 if ((litValue = (int) ulFromVal (vright)) > 1)
5853 werror (W_BAD_COMPARE);
5859 switch (root->opval.op)
5861 case '>': /* bit value greater than 1 cannot be */
5862 werror (W_BAD_COMPARE);
5866 case '<': /* bit value < 1 means 0 */
5868 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5871 case LE_OP: /* bit value <= 1 means no check */
5872 optExpr = newAst_VALUE (vright);
5875 case GE_OP: /* bit value >= 1 means only check for = */
5877 optExpr = newAst_VALUE (vleft);
5882 { /* literal is zero */
5883 switch (root->opval.op)
5885 case '<': /* bit value < 0 cannot be */
5886 werror (W_BAD_COMPARE);
5890 case '>': /* bit value > 0 means 1 */
5892 optExpr = newAst_VALUE (vleft);
5895 case LE_OP: /* bit value <= 0 means no check */
5896 case GE_OP: /* bit value >= 0 means no check */
5897 werror (W_BAD_COMPARE);
5901 case EQ_OP: /* bit == 0 means ! of bit */
5902 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5906 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5907 } /* end-of-if of BITVAR */
5913 /*-----------------------------------------------------------------*/
5914 /* addSymToBlock : adds the symbol to the first block we find */
5915 /*-----------------------------------------------------------------*/
5917 addSymToBlock (symbol * sym, ast * tree)
5919 /* reached end of tree or a leaf */
5920 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5924 if (IS_AST_OP (tree) &&
5925 tree->opval.op == BLOCK)
5928 symbol *lsym = copySymbol (sym);
5930 lsym->next = AST_VALUES (tree, sym);
5931 AST_VALUES (tree, sym) = lsym;
5935 addSymToBlock (sym, tree->left);
5936 addSymToBlock (sym, tree->right);
5939 /*-----------------------------------------------------------------*/
5940 /* processRegParms - do processing for register parameters */
5941 /*-----------------------------------------------------------------*/
5943 processRegParms (value * args, ast * body)
5947 if (IS_REGPARM (args->etype))
5948 addSymToBlock (args->sym, body);
5953 /*-----------------------------------------------------------------*/
5954 /* resetParmKey - resets the operandkeys for the symbols */
5955 /*-----------------------------------------------------------------*/
5956 DEFSETFUNC (resetParmKey)
5969 /*------------------------------------------------------------------*/
5970 /* fixupInlineLabel - change a label in an inlined function so that */
5971 /* it is always unique no matter how many times */
5972 /* the function is inlined. */
5973 /*------------------------------------------------------------------*/
5975 fixupInlineLabel (symbol * sym)
5977 char name[SDCC_NAME_MAX + 1];
5979 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5980 strcpy (sym->name, name);
5984 /*------------------------------------------------------------------*/
5985 /* copyAstLoc - copy location information (file, line, block, etc.) */
5986 /* from one ast node to another */
5987 /*------------------------------------------------------------------*/
5989 copyAstLoc (ast * dest, ast * src)
5991 dest->filename = src->filename;
5992 dest->lineno = src->lineno;
5993 dest->level = src->level;
5994 dest->block = src->block;
5995 dest->seqPoint = src->seqPoint;
6000 /*-----------------------------------------------------------------*/
6001 /* fixupInline - perform various fixups on an inline function tree */
6002 /* to take into account that it is no longer a */
6003 /* stand-alone function. */
6004 /*-----------------------------------------------------------------*/
6006 fixupInline (ast * tree, int level)
6008 tree->block = currBlockno;
6010 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6017 /* Add any declared variables back into the symbol table */
6018 decls = tree->values.sym;
6021 decls->level = level;
6022 decls->block = currBlockno;
6023 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6024 decls = decls->next;
6028 tree->level = level;
6030 /* Update symbols */
6031 if (IS_AST_VALUE (tree) &&
6032 tree->opval.val->sym)
6034 symbol * sym = tree->opval.val->sym;
6037 sym->block = currBlockno;
6040 SYM_SPIL_LOC (sym) = NULL;
6043 /* If the symbol is a label, we need to renumber it */
6045 fixupInlineLabel (sym);
6048 /* Update IFX target labels */
6049 if (tree->type == EX_OP && tree->opval.op == IFX)
6051 if (tree->trueLabel)
6052 fixupInlineLabel (tree->trueLabel);
6053 if (tree->falseLabel)
6054 fixupInlineLabel (tree->falseLabel);
6057 /* Replace RETURN with optional assignment and a GOTO to the end */
6058 /* of the inlined function */
6059 if (tree->type == EX_OP && tree->opval.op == RETURN)
6061 ast * assignTree = NULL;
6064 if (inlineState.retsym && tree->right)
6066 assignTree = newNode ('=',
6067 newAst_VALUE (symbolVal (inlineState.retsym)),
6069 copyAstLoc (assignTree, tree);
6072 gotoTree = newNode (GOTO,
6073 newAst_VALUE (symbolVal (inlineState.retlab)),
6075 copyAstLoc (gotoTree, tree);
6077 tree->opval.op = NULLOP;
6078 tree->left = assignTree;
6079 tree->right = gotoTree;
6082 /* Update any children */
6084 fixupInline (tree->left, level);
6086 fixupInline (tree->right, level);
6088 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6090 symbol * label = tree->left->opval.val->sym;
6092 label->key = labelKey++;
6093 /* Add this label back into the symbol table */
6094 addSym (LabelTab, label, label->name, label->level, 0, 0);
6098 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6104 /*-----------------------------------------------------------------*/
6105 /* inlineAddDecl - add a variable declaration to an ast block. It */
6106 /* is also added to the symbol table if addSymTab */
6108 /*-----------------------------------------------------------------*/
6110 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6113 SYM_SPIL_LOC (sym) = NULL;
6117 symbol **decl = &(block->values.sym);
6119 sym->level = block->level;
6120 sym->block = block->block;
6124 if (strcmp ((*decl)->name, sym->name) == 0)
6126 decl = &( (*decl)->next );
6132 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6138 /*-----------------------------------------------------------------*/
6139 /* inlineTempVar - create a temporary variable for inlining */
6140 /*-----------------------------------------------------------------*/
6142 inlineTempVar (sym_link * type, int level)
6146 sym = newSymbol (genSymName(level), level );
6147 sym->type = copyLinkChain (type);
6148 sym->etype = getSpec(sym->type);
6149 SPEC_SCLS (sym->etype) = S_AUTO;
6150 SPEC_OCLS (sym->etype) = NULL;
6151 SPEC_EXTR (sym->etype) = 0;
6152 SPEC_STAT (sym->etype) = 0;
6153 if IS_SPEC (sym->type)
6154 SPEC_VOLATILE (sym->type) = 0;
6156 DCL_PTR_VOLATILE (sym->type) = 0;
6157 SPEC_ABSA (sym->etype) = 0;
6163 /*-----------------------------------------------------------------*/
6164 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6165 /*-----------------------------------------------------------------*/
6167 inlineFindParmRecurse (ast * parms, int *index)
6172 if (parms->type == EX_OP && parms->opval.op == PARAM)
6176 p=inlineFindParmRecurse (parms->left, index);
6179 p=inlineFindParmRecurse (parms->right, index);
6190 /*-----------------------------------------------------------------*/
6191 /* inlineFindParm - search an ast tree of parameters to find one */
6192 /* at a particular index (0=first parameter). */
6193 /* Returns NULL if not found. */
6194 /*-----------------------------------------------------------------*/
6196 inlineFindParm (ast * parms, int index)
6198 return inlineFindParmRecurse (parms, &index);
6201 /*-----------------------------------------------------------------*/
6202 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6203 /*-----------------------------------------------------------------*/
6205 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6212 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6213 if (tempBlockno > maxBlockno)
6214 maxBlockno = tempBlockno;
6216 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6217 if (tempBlockno > maxBlockno)
6218 maxBlockno = tempBlockno;
6220 if (tree->block > maxBlockno)
6221 maxBlockno = tree->block;
6228 /*-----------------------------------------------------------------*/
6229 /* expandInlineFuncs - replace calls to inline functions with the */
6230 /* function itself */
6231 /*-----------------------------------------------------------------*/
6233 expandInlineFuncs (ast * tree, ast * block)
6235 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6236 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6238 symbol * func = tree->left->opval.val->sym;
6241 /* The symbol is probably not bound yet, so find the real one */
6242 csym = findSymWithLevel (SymbolTab, func);
6246 /* Is this an inline function that we can inline? */
6247 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6249 symbol * retsym = NULL;
6257 /* Generate a label for the inlined function to branch to */
6258 /* in case it contains a return statement */
6259 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6262 inlineState.retlab = retlab;
6264 /* Build the subtree for the inlined function in the form: */
6265 /* { //inlinetree block */
6266 /* { //inlinetree2 block */
6267 /* inline_function_code; */
6271 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6272 copyAstLoc (temptree, tree);
6273 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6274 copyAstLoc (temptree, tree);
6275 temptree = newNode (BLOCK, NULL, temptree);
6276 copyAstLoc (temptree, tree);
6277 inlinetree2 = temptree;
6278 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6279 copyAstLoc (inlinetree, tree);
6281 /* To pass parameters to the inlined function, we need some */
6282 /* intermediate variables. This avoids scoping problems */
6283 /* when the parameter declaration names are used differently */
6284 /* during the function call. For example, a function */
6285 /* declared as func(int x, int y) but called as func(y,x). */
6286 /* { //inlinetree block */
6287 /* type1 temparg1; */
6289 /* typen tempargn; */
6290 /* temparg1 = argument1; */
6292 /* tempargn = argumentn; */
6293 /* { //inlinetree2 block */
6297 /* param1 = temparg1; */
6299 /* paramn = tempargn; */
6300 /* inline_function_code; */
6304 args = FUNC_ARGS (func->type);
6311 ast * passedarg = inlineFindParm (tree->right, argIndex);
6315 werror(E_TOO_FEW_PARMS);
6319 temparg = inlineTempVar (args->sym->type, tree->level+1);
6320 inlineAddDecl (temparg, inlinetree, FALSE);
6322 assigntree = newNode ('=',
6323 newAst_VALUE (symbolVal (temparg)),
6325 inlinetree->right = newNode (NULLOP,
6329 parm = copySymbol (args->sym);
6330 inlineAddDecl (parm, inlinetree2, FALSE);
6333 assigntree = newNode ('=',
6334 newAst_VALUE (symbolVal (parm)),
6335 newAst_VALUE (symbolVal (temparg)));
6336 inlinetree2->right = newNode (NULLOP,
6338 inlinetree2->right);
6345 /* Handle the return type */
6346 if (!IS_VOID (func->type->next))
6348 /* Create a temporary symbol to hold the return value and */
6349 /* join it with the inlined function using the comma */
6350 /* operator. The fixupInline function will take care of */
6351 /* changing return statements into assignments to retsym. */
6352 /* (parameter passing and return label omitted for clarity) */
6353 /* rettype retsym; */
6355 /* {{inline_function_code}}, retsym */
6357 retsym = inlineTempVar (func->type->next, tree->level);
6358 inlineAddDecl (retsym, block, TRUE);
6360 tree->opval.op = ',';
6361 tree->left = inlinetree;
6362 tree->right = newAst_VALUE (symbolVal (retsym));
6366 tree->opval.op = NULLOP;
6368 tree->right = inlinetree;
6370 inlineState.retsym = retsym;
6372 /* Renumber the various internal counters on the inlined */
6373 /* function's tree nodes and symbols. Add the inlined */
6374 /* function's local variables to the appropriate scope(s). */
6375 /* Convert inlined return statements to an assignment to */
6376 /* retsym (if needed) and a goto retlab. */
6377 fixupInline (inlinetree, inlinetree->level);
6378 inlineState.count++;
6383 /* Recursively continue to search for functions to inline. */
6384 if (IS_AST_OP (tree))
6386 if (tree->opval.op == BLOCK)
6390 expandInlineFuncs (tree->left, block);
6392 expandInlineFuncs (tree->right, block);
6397 /*-----------------------------------------------------------------*/
6398 /* createFunction - This is the key node that calls the iCode for */
6399 /* generating the code for a function. Note code */
6400 /* is generated function by function, later when */
6401 /* add inter-procedural analysis this will change */
6402 /*-----------------------------------------------------------------*/
6404 createFunction (symbol * name, ast * body)
6410 iCode *piCode = NULL;
6413 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6414 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6416 /* if check function return 0 then some problem */
6417 if (checkFunction (name, NULL) == 0)
6420 /* create a dummy block if none exists */
6422 body = newNode (BLOCK, NULL, NULL);
6426 /* check if the function name already in the symbol table */
6427 if ((csym = findSym (SymbolTab, NULL, name->name)))
6430 /* special case for compiler defined functions
6431 we need to add the name to the publics list : this
6432 actually means we are now compiling the compiler
6436 addSet (&publics, name);
6441 addSymChain (&name);
6442 allocVariables (name);
6444 name->lastLine = lexLineno;
6447 /* set the stack pointer */
6448 stackPtr = -port->stack.direction * port->stack.call_overhead;
6451 if (IFFUNC_ISISR (name->type))
6452 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6454 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6456 if (options.useXstack)
6457 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6459 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6462 fetype = getSpec (name->type); /* get the specifier for the function */
6463 /* if this is a reentrant function then */
6464 if (IFFUNC_ISREENT (name->type))
6467 inlineState.count = 0;
6468 savedBlockno = currBlockno;
6469 currBlockno = inlineFindMaxBlockno (body, 0);
6470 expandInlineFuncs (body, NULL);
6471 currBlockno = savedBlockno;
6473 if (FUNC_ISINLINE (name->type))
6474 name->funcTree = copyAst (body);
6476 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6478 /* do processing for parameters that are passed in registers */
6479 processRegParms (FUNC_ARGS(name->type), body);
6481 /* set the stack pointer */
6485 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6487 /* allocate & autoinit the block variables */
6488 processBlockVars (body, &stack, ALLOCATE);
6490 /* name needs to be mangled */
6491 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6493 body = resolveSymbols (body); /* resolve the symbols */
6494 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6496 /* save the stack information */
6497 if (options.useXstack)
6498 name->xstack = SPEC_STAK (fetype) = stack;
6500 name->stack = SPEC_STAK (fetype) = stack;
6502 ex = newAst_VALUE (symbolVal (name)); /* create name */
6503 ex = newNode (FUNCTION, ex, body);
6504 ex->values.args = FUNC_ARGS(name->type);
6506 if (options.dump_tree)
6511 /* Do not generate code for inline functions unless extern also. */
6513 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6516 /* Temporary hack: always generate code for static inline functions. */
6517 /* Ideally static inline functions should only be generated if needed. */
6518 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6522 /* create the node & generate intermediate code */
6524 codeOutBuf = &code->oBuf;
6525 piCode = iCodeFromAst (ex);
6526 name->generated = 1;
6531 eBBlockFromiCode (piCode);
6533 /* if there are any statics then do them */
6536 GcurMemmap = statsg;
6537 codeOutBuf = &statsg->oBuf;
6538 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6544 /* dealloc the block variables */
6545 processBlockVars (body, &stack, DEALLOCATE);
6546 outputDebugStackSymbols();
6547 /* deallocate paramaters */
6548 deallocParms (FUNC_ARGS(name->type));
6550 if (IFFUNC_ISREENT (name->type))
6553 /* we are done freeup memory & cleanup */
6555 if (port->reset_labelKey) labelKey = 1;
6557 FUNC_HASBODY(name->type) = 1;
6558 addSet (&operKeyReset, name);
6559 applyToSet (operKeyReset, resetParmKey);
6564 cleanUpLevel (LabelTab, 0);
6565 cleanUpBlock (StructTab, 1);
6566 cleanUpBlock (TypedefTab, 1);
6568 xstack->syms = NULL;
6569 istack->syms = NULL;
6574 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6575 /*-----------------------------------------------------------------*/
6576 /* ast_print : prints the ast (for debugging purposes) */
6577 /*-----------------------------------------------------------------*/
6579 void ast_print (ast * tree, FILE *outfile, int indent)
6584 /* can print only decorated trees */
6585 if (!tree->decorated) return;
6587 /* if any child is an error | this one is an error do nothing */
6588 if (tree->isError ||
6589 (tree->left && tree->left->isError) ||
6590 (tree->right && tree->right->isError)) {
6591 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6595 /* print the line */
6596 /* if not block & function */
6597 if (tree->type == EX_OP &&
6598 (tree->opval.op != FUNCTION &&
6599 tree->opval.op != BLOCK &&
6600 tree->opval.op != NULLOP)) {
6603 if (tree->opval.op == FUNCTION) {
6605 value *args=FUNC_ARGS(tree->left->opval.val->type);
6606 fprintf(outfile,"FUNCTION (%s=%p) type (",
6607 tree->left->opval.val->name, tree);
6608 printTypeChain (tree->left->opval.val->type->next,outfile);
6609 fprintf(outfile,") args (");
6612 fprintf (outfile, ", ");
6614 printTypeChain (args ? args->type : NULL, outfile);
6616 args= args ? args->next : NULL;
6618 fprintf(outfile,")\n");
6619 ast_print(tree->left,outfile,indent);
6620 ast_print(tree->right,outfile,indent);
6623 if (tree->opval.op == BLOCK) {
6624 symbol *decls = tree->values.sym;
6625 INDENT(indent,outfile);
6626 fprintf(outfile,"{\n");
6628 INDENT(indent+2,outfile);
6629 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6630 decls->name, decls);
6631 printTypeChain(decls->type,outfile);
6632 fprintf(outfile,")\n");
6634 decls = decls->next;
6636 ast_print(tree->right,outfile,indent+2);
6637 INDENT(indent,outfile);
6638 fprintf(outfile,"}\n");
6641 if (tree->opval.op == NULLOP) {
6642 ast_print(tree->left,outfile,indent);
6643 ast_print(tree->right,outfile,indent);
6646 INDENT(indent,outfile);
6648 /*------------------------------------------------------------------*/
6649 /*----------------------------*/
6650 /* leaf has been reached */
6651 /*----------------------------*/
6652 /* if this is of type value */
6653 /* just get the type */
6654 if (tree->type == EX_VALUE) {
6656 if (IS_LITERAL (tree->opval.val->etype)) {
6657 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6658 if (SPEC_USIGN (tree->opval.val->etype))
6659 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6661 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6662 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6663 floatFromVal(tree->opval.val));
6664 } else if (tree->opval.val->sym) {
6665 /* if the undefined flag is set then give error message */
6666 if (tree->opval.val->sym->undefined) {
6667 fprintf(outfile,"UNDEFINED SYMBOL ");
6669 fprintf(outfile,"SYMBOL ");
6671 fprintf(outfile,"(%s=%p @ %p)",
6672 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6675 fprintf(outfile," type (");
6676 printTypeChain(tree->ftype,outfile);
6677 fprintf(outfile,")\n");
6679 fprintf(outfile,"\n");
6684 /* if type link for the case of cast */
6685 if (tree->type == EX_LINK) {
6686 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6687 printTypeChain(tree->opval.lnk,outfile);
6688 fprintf(outfile,")\n");
6693 /* depending on type of operator do */
6695 switch (tree->opval.op) {
6696 /*------------------------------------------------------------------*/
6697 /*----------------------------*/
6699 /*----------------------------*/
6701 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6702 printTypeChain(tree->ftype,outfile);
6703 fprintf(outfile,")\n");
6704 ast_print(tree->left,outfile,indent+2);
6705 ast_print(tree->right,outfile,indent+2);
6708 /*------------------------------------------------------------------*/
6709 /*----------------------------*/
6711 /*----------------------------*/
6713 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6714 printTypeChain(tree->ftype,outfile);
6715 fprintf(outfile,")\n");
6716 ast_print(tree->left,outfile,indent+2);
6717 ast_print(tree->right,outfile,indent+2);
6720 /*------------------------------------------------------------------*/
6721 /*----------------------------*/
6722 /* struct/union pointer */
6723 /*----------------------------*/
6725 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6726 printTypeChain(tree->ftype,outfile);
6727 fprintf(outfile,")\n");
6728 ast_print(tree->left,outfile,indent+2);
6729 ast_print(tree->right,outfile,indent+2);
6732 /*------------------------------------------------------------------*/
6733 /*----------------------------*/
6734 /* ++/-- operation */
6735 /*----------------------------*/
6738 fprintf(outfile,"post-");
6740 fprintf(outfile,"pre-");
6741 fprintf(outfile,"INC_OP (%p) type (",tree);
6742 printTypeChain(tree->ftype,outfile);
6743 fprintf(outfile,")\n");
6744 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6745 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6750 fprintf(outfile,"post-");
6752 fprintf(outfile,"pre-");
6753 fprintf(outfile,"DEC_OP (%p) type (",tree);
6754 printTypeChain(tree->ftype,outfile);
6755 fprintf(outfile,")\n");
6756 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6757 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6760 /*------------------------------------------------------------------*/
6761 /*----------------------------*/
6763 /*----------------------------*/
6766 fprintf(outfile,"& (%p) type (",tree);
6767 printTypeChain(tree->ftype,outfile);
6768 fprintf(outfile,")\n");
6769 ast_print(tree->left,outfile,indent+2);
6770 ast_print(tree->right,outfile,indent+2);
6772 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6773 printTypeChain(tree->ftype,outfile);
6774 fprintf(outfile,")\n");
6775 ast_print(tree->left,outfile,indent+2);
6776 ast_print(tree->right,outfile,indent+2);
6779 /*----------------------------*/
6781 /*----------------------------*/
6783 fprintf(outfile,"OR (%p) type (",tree);
6784 printTypeChain(tree->ftype,outfile);
6785 fprintf(outfile,")\n");
6786 ast_print(tree->left,outfile,indent+2);
6787 ast_print(tree->right,outfile,indent+2);
6789 /*------------------------------------------------------------------*/
6790 /*----------------------------*/
6792 /*----------------------------*/
6794 fprintf(outfile,"XOR (%p) type (",tree);
6795 printTypeChain(tree->ftype,outfile);
6796 fprintf(outfile,")\n");
6797 ast_print(tree->left,outfile,indent+2);
6798 ast_print(tree->right,outfile,indent+2);
6801 /*------------------------------------------------------------------*/
6802 /*----------------------------*/
6804 /*----------------------------*/
6806 fprintf(outfile,"DIV (%p) type (",tree);
6807 printTypeChain(tree->ftype,outfile);
6808 fprintf(outfile,")\n");
6809 ast_print(tree->left,outfile,indent+2);
6810 ast_print(tree->right,outfile,indent+2);
6812 /*------------------------------------------------------------------*/
6813 /*----------------------------*/
6815 /*----------------------------*/
6817 fprintf(outfile,"MOD (%p) type (",tree);
6818 printTypeChain(tree->ftype,outfile);
6819 fprintf(outfile,")\n");
6820 ast_print(tree->left,outfile,indent+2);
6821 ast_print(tree->right,outfile,indent+2);
6824 /*------------------------------------------------------------------*/
6825 /*----------------------------*/
6826 /* address dereference */
6827 /*----------------------------*/
6828 case '*': /* can be unary : if right is null then unary operation */
6830 fprintf(outfile,"DEREF (%p) type (",tree);
6831 printTypeChain(tree->ftype,outfile);
6832 fprintf(outfile,")\n");
6833 ast_print(tree->left,outfile,indent+2);
6836 /*------------------------------------------------------------------*/
6837 /*----------------------------*/
6838 /* multiplication */
6839 /*----------------------------*/
6840 fprintf(outfile,"MULT (%p) type (",tree);
6841 printTypeChain(tree->ftype,outfile);
6842 fprintf(outfile,")\n");
6843 ast_print(tree->left,outfile,indent+2);
6844 ast_print(tree->right,outfile,indent+2);
6848 /*------------------------------------------------------------------*/
6849 /*----------------------------*/
6850 /* unary '+' operator */
6851 /*----------------------------*/
6855 fprintf(outfile,"UPLUS (%p) type (",tree);
6856 printTypeChain(tree->ftype,outfile);
6857 fprintf(outfile,")\n");
6858 ast_print(tree->left,outfile,indent+2);
6860 /*------------------------------------------------------------------*/
6861 /*----------------------------*/
6863 /*----------------------------*/
6864 fprintf(outfile,"ADD (%p) type (",tree);
6865 printTypeChain(tree->ftype,outfile);
6866 fprintf(outfile,")\n");
6867 ast_print(tree->left,outfile,indent+2);
6868 ast_print(tree->right,outfile,indent+2);
6871 /*------------------------------------------------------------------*/
6872 /*----------------------------*/
6874 /*----------------------------*/
6875 case '-': /* can be unary */
6877 fprintf(outfile,"UMINUS (%p) type (",tree);
6878 printTypeChain(tree->ftype,outfile);
6879 fprintf(outfile,")\n");
6880 ast_print(tree->left,outfile,indent+2);
6882 /*------------------------------------------------------------------*/
6883 /*----------------------------*/
6885 /*----------------------------*/
6886 fprintf(outfile,"SUB (%p) type (",tree);
6887 printTypeChain(tree->ftype,outfile);
6888 fprintf(outfile,")\n");
6889 ast_print(tree->left,outfile,indent+2);
6890 ast_print(tree->right,outfile,indent+2);
6893 /*------------------------------------------------------------------*/
6894 /*----------------------------*/
6896 /*----------------------------*/
6898 fprintf(outfile,"COMPL (%p) type (",tree);
6899 printTypeChain(tree->ftype,outfile);
6900 fprintf(outfile,")\n");
6901 ast_print(tree->left,outfile,indent+2);
6903 /*------------------------------------------------------------------*/
6904 /*----------------------------*/
6906 /*----------------------------*/
6908 fprintf(outfile,"NOT (%p) type (",tree);
6909 printTypeChain(tree->ftype,outfile);
6910 fprintf(outfile,")\n");
6911 ast_print(tree->left,outfile,indent+2);
6913 /*------------------------------------------------------------------*/
6914 /*----------------------------*/
6916 /*----------------------------*/
6918 fprintf(outfile,"RRC (%p) type (",tree);
6919 printTypeChain(tree->ftype,outfile);
6920 fprintf(outfile,")\n");
6921 ast_print(tree->left,outfile,indent+2);
6925 fprintf(outfile,"RLC (%p) type (",tree);
6926 printTypeChain(tree->ftype,outfile);
6927 fprintf(outfile,")\n");
6928 ast_print(tree->left,outfile,indent+2);
6931 fprintf(outfile,"SWAP (%p) type (",tree);
6932 printTypeChain(tree->ftype,outfile);
6933 fprintf(outfile,")\n");
6934 ast_print(tree->left,outfile,indent+2);
6937 fprintf(outfile,"GETHBIT (%p) type (",tree);
6938 printTypeChain(tree->ftype,outfile);
6939 fprintf(outfile,")\n");
6940 ast_print(tree->left,outfile,indent+2);
6943 fprintf(outfile,"GETABIT (%p) type (",tree);
6944 printTypeChain(tree->ftype,outfile);
6945 fprintf(outfile,")\n");
6946 ast_print(tree->left,outfile,indent+2);
6947 ast_print(tree->right,outfile,indent+2);
6950 fprintf(outfile,"GETBYTE (%p) type (",tree);
6951 printTypeChain(tree->ftype,outfile);
6952 fprintf(outfile,")\n");
6953 ast_print(tree->left,outfile,indent+2);
6954 ast_print(tree->right,outfile,indent+2);
6957 fprintf(outfile,"GETWORD (%p) type (",tree);
6958 printTypeChain(tree->ftype,outfile);
6959 fprintf(outfile,")\n");
6960 ast_print(tree->left,outfile,indent+2);
6961 ast_print(tree->right,outfile,indent+2);
6964 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6965 printTypeChain(tree->ftype,outfile);
6966 fprintf(outfile,")\n");
6967 ast_print(tree->left,outfile,indent+2);
6968 ast_print(tree->right,outfile,indent+2);
6971 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6972 printTypeChain(tree->ftype,outfile);
6973 fprintf(outfile,")\n");
6974 ast_print(tree->left,outfile,indent+2);
6975 ast_print(tree->right,outfile,indent+2);
6977 /*------------------------------------------------------------------*/
6978 /*----------------------------*/
6980 /*----------------------------*/
6981 case CAST: /* change the type */
6982 fprintf(outfile,"CAST (%p) from type (",tree);
6983 printTypeChain(tree->right->ftype,outfile);
6984 fprintf(outfile,") to type (");
6985 printTypeChain(tree->ftype,outfile);
6986 fprintf(outfile,")\n");
6987 ast_print(tree->right,outfile,indent+2);
6991 fprintf(outfile,"ANDAND (%p) type (",tree);
6992 printTypeChain(tree->ftype,outfile);
6993 fprintf(outfile,")\n");
6994 ast_print(tree->left,outfile,indent+2);
6995 ast_print(tree->right,outfile,indent+2);
6998 fprintf(outfile,"OROR (%p) type (",tree);
6999 printTypeChain(tree->ftype,outfile);
7000 fprintf(outfile,")\n");
7001 ast_print(tree->left,outfile,indent+2);
7002 ast_print(tree->right,outfile,indent+2);
7005 /*------------------------------------------------------------------*/
7006 /*----------------------------*/
7007 /* comparison operators */
7008 /*----------------------------*/
7010 fprintf(outfile,"GT(>) (%p) type (",tree);
7011 printTypeChain(tree->ftype,outfile);
7012 fprintf(outfile,")\n");
7013 ast_print(tree->left,outfile,indent+2);
7014 ast_print(tree->right,outfile,indent+2);
7017 fprintf(outfile,"LT(<) (%p) type (",tree);
7018 printTypeChain(tree->ftype,outfile);
7019 fprintf(outfile,")\n");
7020 ast_print(tree->left,outfile,indent+2);
7021 ast_print(tree->right,outfile,indent+2);
7024 fprintf(outfile,"LE(<=) (%p) type (",tree);
7025 printTypeChain(tree->ftype,outfile);
7026 fprintf(outfile,")\n");
7027 ast_print(tree->left,outfile,indent+2);
7028 ast_print(tree->right,outfile,indent+2);
7031 fprintf(outfile,"GE(>=) (%p) type (",tree);
7032 printTypeChain(tree->ftype,outfile);
7033 fprintf(outfile,")\n");
7034 ast_print(tree->left,outfile,indent+2);
7035 ast_print(tree->right,outfile,indent+2);
7038 fprintf(outfile,"EQ(==) (%p) type (",tree);
7039 printTypeChain(tree->ftype,outfile);
7040 fprintf(outfile,")\n");
7041 ast_print(tree->left,outfile,indent+2);
7042 ast_print(tree->right,outfile,indent+2);
7045 fprintf(outfile,"NE(!=) (%p) type (",tree);
7046 printTypeChain(tree->ftype,outfile);
7047 fprintf(outfile,")\n");
7048 ast_print(tree->left,outfile,indent+2);
7049 ast_print(tree->right,outfile,indent+2);
7050 /*------------------------------------------------------------------*/
7051 /*----------------------------*/
7053 /*----------------------------*/
7054 case SIZEOF: /* evaluate wihout code generation */
7055 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7058 /*------------------------------------------------------------------*/
7059 /*----------------------------*/
7060 /* conditional operator '?' */
7061 /*----------------------------*/
7063 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7064 printTypeChain(tree->ftype,outfile);
7065 fprintf(outfile,")\n");
7066 ast_print(tree->left,outfile,indent+2);
7067 ast_print(tree->right,outfile,indent+2);
7071 fprintf(outfile,"COLON(:) (%p) type (",tree);
7072 printTypeChain(tree->ftype,outfile);
7073 fprintf(outfile,")\n");
7074 ast_print(tree->left,outfile,indent+2);
7075 ast_print(tree->right,outfile,indent+2);
7078 /*------------------------------------------------------------------*/
7079 /*----------------------------*/
7080 /* assignment operators */
7081 /*----------------------------*/
7083 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7084 printTypeChain(tree->ftype,outfile);
7085 fprintf(outfile,")\n");
7086 ast_print(tree->left,outfile,indent+2);
7087 ast_print(tree->right,outfile,indent+2);
7090 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7091 printTypeChain(tree->ftype,outfile);
7092 fprintf(outfile,")\n");
7093 ast_print(tree->left,outfile,indent+2);
7094 ast_print(tree->right,outfile,indent+2);
7097 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7098 printTypeChain(tree->ftype,outfile);
7099 fprintf(outfile,")\n");
7100 ast_print(tree->left,outfile,indent+2);
7101 ast_print(tree->right,outfile,indent+2);
7104 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7105 printTypeChain(tree->ftype,outfile);
7106 fprintf(outfile,")\n");
7107 ast_print(tree->left,outfile,indent+2);
7108 ast_print(tree->right,outfile,indent+2);
7111 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7112 printTypeChain(tree->ftype,outfile);
7113 fprintf(outfile,")\n");
7114 ast_print(tree->left,outfile,indent+2);
7115 ast_print(tree->right,outfile,indent+2);
7118 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7119 printTypeChain(tree->ftype,outfile);
7120 fprintf(outfile,")\n");
7121 ast_print(tree->left,outfile,indent+2);
7122 ast_print(tree->right,outfile,indent+2);
7125 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7126 printTypeChain(tree->ftype,outfile);
7127 fprintf(outfile,")\n");
7128 ast_print(tree->left,outfile,indent+2);
7129 ast_print(tree->right,outfile,indent+2);
7131 /*------------------------------------------------------------------*/
7132 /*----------------------------*/
7134 /*----------------------------*/
7136 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7137 printTypeChain(tree->ftype,outfile);
7138 fprintf(outfile,")\n");
7139 ast_print(tree->left,outfile,indent+2);
7140 ast_print(tree->right,outfile,indent+2);
7142 /*------------------------------------------------------------------*/
7143 /*----------------------------*/
7145 /*----------------------------*/
7147 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7148 printTypeChain(tree->ftype,outfile);
7149 fprintf(outfile,")\n");
7150 ast_print(tree->left,outfile,indent+2);
7151 ast_print(tree->right,outfile,indent+2);
7153 /*------------------------------------------------------------------*/
7154 /*----------------------------*/
7155 /* straight assignemnt */
7156 /*----------------------------*/
7158 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7159 printTypeChain(tree->ftype,outfile);
7160 fprintf(outfile,")\n");
7161 ast_print(tree->left,outfile,indent+2);
7162 ast_print(tree->right,outfile,indent+2);
7164 /*------------------------------------------------------------------*/
7165 /*----------------------------*/
7166 /* comma operator */
7167 /*----------------------------*/
7169 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7170 printTypeChain(tree->ftype,outfile);
7171 fprintf(outfile,")\n");
7172 ast_print(tree->left,outfile,indent+2);
7173 ast_print(tree->right,outfile,indent+2);
7175 /*------------------------------------------------------------------*/
7176 /*----------------------------*/
7178 /*----------------------------*/
7181 fprintf(outfile,"CALL (%p) type (",tree);
7182 printTypeChain(tree->ftype,outfile);
7183 fprintf(outfile,")\n");
7184 ast_print(tree->left,outfile,indent+2);
7185 ast_print(tree->right,outfile,indent+2);
7188 fprintf(outfile,"PARMS\n");
7189 ast_print(tree->left,outfile,indent+2);
7190 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7191 ast_print(tree->right,outfile,indent+2);
7194 /*------------------------------------------------------------------*/
7195 /*----------------------------*/
7196 /* return statement */
7197 /*----------------------------*/
7199 fprintf(outfile,"RETURN (%p) type (",tree);
7201 printTypeChain(tree->right->ftype,outfile);
7203 fprintf(outfile,")\n");
7204 ast_print(tree->right,outfile,indent+2);
7206 /*------------------------------------------------------------------*/
7207 /*----------------------------*/
7208 /* label statement */
7209 /*----------------------------*/
7211 fprintf(outfile,"LABEL (%p)\n",tree);
7212 ast_print(tree->left,outfile,indent+2);
7213 ast_print(tree->right,outfile,indent);
7215 /*------------------------------------------------------------------*/
7216 /*----------------------------*/
7217 /* switch statement */
7218 /*----------------------------*/
7222 fprintf(outfile,"SWITCH (%p) ",tree);
7223 ast_print(tree->left,outfile,0);
7224 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7225 INDENT(indent+2,outfile);
7226 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7227 (int) ulFromVal(val),
7228 tree->values.switchVals.swNum,
7229 (int) ulFromVal(val));
7231 ast_print(tree->right,outfile,indent);
7234 /*------------------------------------------------------------------*/
7235 /*----------------------------*/
7237 /*----------------------------*/
7239 fprintf(outfile,"IF (%p) \n",tree);
7240 ast_print(tree->left,outfile,indent+2);
7241 if (tree->trueLabel) {
7242 INDENT(indent+2,outfile);
7243 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7245 if (tree->falseLabel) {
7246 INDENT(indent+2,outfile);
7247 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7249 ast_print(tree->right,outfile,indent+2);
7251 /*----------------------------*/
7252 /* goto Statement */
7253 /*----------------------------*/
7255 fprintf(outfile,"GOTO (%p) \n",tree);
7256 ast_print(tree->left,outfile,indent+2);
7257 fprintf(outfile,"\n");
7259 /*------------------------------------------------------------------*/
7260 /*----------------------------*/
7262 /*----------------------------*/
7264 fprintf(outfile,"FOR (%p) \n",tree);
7265 if (AST_FOR( tree, initExpr)) {
7266 INDENT(indent+2,outfile);
7267 fprintf(outfile,"INIT EXPR ");
7268 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7270 if (AST_FOR( tree, condExpr)) {
7271 INDENT(indent+2,outfile);
7272 fprintf(outfile,"COND EXPR ");
7273 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7275 if (AST_FOR( tree, loopExpr)) {
7276 INDENT(indent+2,outfile);
7277 fprintf(outfile,"LOOP EXPR ");
7278 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7280 fprintf(outfile,"FOR LOOP BODY \n");
7281 ast_print(tree->left,outfile,indent+2);
7284 fprintf(outfile,"CRITICAL (%p) \n",tree);
7285 ast_print(tree->left,outfile,indent+2);
7293 ast_print(t,stdout,0);
7296 /*-----------------------------------------------------------------*/
7297 /* astErrors : returns non-zero if errors present in tree */
7298 /*-----------------------------------------------------------------*/
7299 int astErrors(ast *t)
7308 if (t->type == EX_VALUE
7309 && t->opval.val->sym
7310 && t->opval.val->sym->undefined)
7313 errors += astErrors(t->left);
7314 errors += astErrors(t->right);