1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
546 /* if this is a label resolve it from the labelTab */
547 if (IS_AST_VALUE (tree) &&
548 tree->opval.val->sym &&
549 tree->opval.val->sym->islbl)
552 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
553 tree->opval.val->sym->name);
556 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
557 tree->opval.val->sym->name);
559 tree->opval.val->sym = csym;
561 goto resolveChildren;
564 /* do only for leafs */
565 if (IS_AST_VALUE (tree) &&
566 tree->opval.val->sym &&
567 !tree->opval.val->sym->implicit)
570 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
572 /* if found in the symbol table & they are not the same */
573 if (csym && tree->opval.val->sym != csym)
575 tree->opval.val->sym = csym;
576 tree->opval.val->type = csym->type;
577 tree->opval.val->etype = csym->etype;
580 /* if not found in the symbol table */
581 /* mark it as undefined & assume it */
582 /* is an integer in data space */
583 if (!csym && !tree->opval.val->sym->implicit)
586 /* if this is a function name then */
587 /* mark it as returning an int */
590 tree->opval.val->sym->type = newLink (DECLARATOR);
591 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
592 tree->opval.val->sym->type->next =
593 tree->opval.val->sym->etype = newIntLink ();
594 tree->opval.val->etype = tree->opval.val->etype;
595 tree->opval.val->type = tree->opval.val->sym->type;
596 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
597 tree->opval.val->sym->name);
598 //tree->opval.val->sym->undefined = 1;
599 allocVariables (tree->opval.val->sym);
603 tree->opval.val->sym->undefined = 1;
604 tree->opval.val->type =
605 tree->opval.val->etype = newIntLink ();
606 tree->opval.val->sym->type =
607 tree->opval.val->sym->etype = newIntLink ();
613 resolveSymbols (tree->left);
614 resolveSymbols (tree->right);
619 /*------------------------------------------------------------------------*/
620 /* setAstFileLine - walks a ast tree & sets the file name and line number */
621 /*------------------------------------------------------------------------*/
622 int setAstFileLine (ast * tree, char *filename, int lineno)
627 tree->filename = filename;
628 tree->lineno = lineno;
629 setAstFileLine (tree->left, filename, lineno);
630 setAstFileLine (tree->right, filename, lineno);
634 /*-----------------------------------------------------------------*/
635 /* funcOfType :- function of type with name */
636 /*-----------------------------------------------------------------*/
638 funcOfType (char *name, sym_link * type, sym_link * argType,
642 /* create the symbol */
643 sym = newSymbol (name, 0);
645 /* setup return value */
646 sym->type = newLink (DECLARATOR);
647 DCL_TYPE (sym->type) = FUNCTION;
648 sym->type->next = copyLinkChain (type);
649 sym->etype = getSpec (sym->type);
650 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
652 /* if arguments required */
656 args = FUNC_ARGS(sym->type) = newValue ();
660 args->type = copyLinkChain (argType);
661 args->etype = getSpec (args->type);
662 SPEC_EXTR(args->etype)=1;
665 args = args->next = newValue ();
672 allocVariables (sym);
677 /*-----------------------------------------------------------------*/
678 /* funcOfTypeVarg :- function of type with name and argtype */
679 /*-----------------------------------------------------------------*/
681 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
686 /* create the symbol */
687 sym = newSymbol (name, 0);
689 /* setup return value */
690 sym->type = newLink (DECLARATOR);
691 DCL_TYPE (sym->type) = FUNCTION;
692 sym->type->next = typeFromStr(rtype);
693 sym->etype = getSpec (sym->type);
695 /* if arguments required */
698 args = FUNC_ARGS(sym->type) = newValue ();
700 for ( i = 0 ; i < nArgs ; i++ ) {
701 args->type = typeFromStr(atypes[i]);
702 args->etype = getSpec (args->type);
703 SPEC_EXTR(args->etype)=1;
704 if ((i + 1) == nArgs) break;
705 args = args->next = newValue ();
712 allocVariables (sym);
717 /*-----------------------------------------------------------------*/
718 /* reverseParms - will reverse a parameter tree */
719 /*-----------------------------------------------------------------*/
721 reverseParms (ast * ptree)
727 /* top down if we find a nonParm tree then quit */
728 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
730 /* The various functions expect the parameter tree to be right heavy. */
731 /* Rotate the tree to be left heavy so that after reversal it is */
732 /* right heavy again. */
733 while ((ttree = ptree->right) && ttree->type == EX_OP &&
734 ttree->opval.op == PARAM)
736 ptree->right = ttree->right;
737 ttree->right = ttree->left;
738 ttree->left = ptree->left;
744 ptree->left = ptree->right;
745 ptree->right = ttree;
747 reverseParms (ptree->left);
748 reverseParms (ptree->right);
754 /*-----------------------------------------------------------------*/
755 /* processParms - makes sure the parameters are okay and do some */
756 /* processing with them */
757 /*-----------------------------------------------------------------*/
759 processParms (ast *func,
762 int *parmNumber, /* unused, although updated */
765 RESULT_TYPE resultType;
768 /* if none of them exist */
769 if (!defParm && !*actParm)
774 if (getenv("DEBUG_SANITY"))
776 fprintf (stderr, "processParms: %s ", defParm->name);
778 /* make sure the type is complete and sane */
779 checkTypeSanity(defParm->etype, defParm->name);
782 if (IS_CODEPTR (func->ftype))
783 functype = func->ftype->next;
785 functype = func->ftype;
787 /* if the function is being called via a pointer & */
788 /* it has not been defined reentrant then we cannot */
789 /* have parameters */
790 /* PIC16 port can... */
791 if (!TARGET_IS_PIC16)
793 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
795 werror (E_NONRENT_ARGS);
801 /* if defined parameters ended but actual parameters */
802 /* exist and this is not defined as a variable arg */
803 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
805 werror (E_TOO_MANY_PARMS);
809 /* if defined parameters present but no actual parameters */
810 if (defParm && !*actParm)
812 werror (E_TOO_FEW_PARMS);
816 /* if this is a PARAM node then match left & right */
817 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
819 (*actParm)->decorated = 1;
820 return (processParms (func, defParm,
821 &(*actParm)->left, parmNumber, FALSE) ||
822 processParms (func, defParm ? defParm->next : NULL,
823 &(*actParm)->right, parmNumber, rightmost));
825 else if (defParm) /* not vararg */
827 /* If we have found a value node by following only right-hand links,
828 * then we know that there are no more values after us.
830 * Therefore, if there are more defined parameters, the caller didn't
833 if (rightmost && defParm->next)
835 werror (E_TOO_FEW_PARMS);
840 /* decorate parameter */
841 resultType = defParm ? getResultTypeFromType (defParm->type) :
843 *actParm = decorateType (*actParm, resultType);
845 if (IS_VOID((*actParm)->ftype))
847 werror (E_VOID_VALUE_USED);
851 /* If this is a varargs function... */
852 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
857 if (IS_CAST_OP (*actParm)
858 || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
860 /* Parameter was explicitly typecast; don't touch it. */
864 ftype = (*actParm)->ftype;
866 /* If it's a char, upcast to int. */
867 if (IS_INTEGRAL (ftype)
868 && (getSize (ftype) < (unsigned) INTSIZE))
870 newType = newAst_LINK(INTTYPE);
873 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
875 newType = newAst_LINK (copyLinkChain(ftype));
876 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
879 if (IS_AGGREGATE (ftype))
881 newType = newAst_LINK (copyLinkChain (ftype));
882 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887 /* cast required; change this op to a cast. */
888 (*actParm)->decorated = 0;
889 *actParm = newNode (CAST, newType, *actParm);
890 (*actParm)->filename = (*actParm)->right->filename;
891 (*actParm)->lineno = (*actParm)->right->lineno;
893 decorateType (*actParm, RESULT_TYPE_NONE);
898 /* if defined parameters ended but actual has not & */
900 if (!defParm && *actParm &&
901 (options.stackAuto || IFFUNC_ISREENT (functype)))
904 resolveSymbols (*actParm);
906 /* the parameter type must be at least castable */
907 if (compareType (defParm->type, (*actParm)->ftype) == 0)
909 werror (E_INCOMPAT_TYPES);
910 printFromToType ((*actParm)->ftype, defParm->type);
914 /* if the parameter is castable then add the cast */
915 if (compareType (defParm->type, (*actParm)->ftype) < 0)
919 resultType = getResultTypeFromType (defParm->etype);
920 pTree = resolveSymbols (copyAst (*actParm));
922 /* now change the current one to a cast */
923 (*actParm)->type = EX_OP;
924 (*actParm)->opval.op = CAST;
925 (*actParm)->left = newAst_LINK (defParm->type);
926 (*actParm)->right = pTree;
927 (*actParm)->decorated = 0; /* force typechecking */
928 decorateType (*actParm, resultType);
931 /* make a copy and change the regparm type to the defined parm */
932 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
933 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
934 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
936 /* if the function is being called via a pointer & */
937 /* this parameter is not passed in registers */
938 /* then the function must be defined reentrant */
939 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
940 !IFFUNC_ISREENT (functype) && !options.stackAuto)
942 werror (E_NONRENT_ARGS);
951 /*-----------------------------------------------------------------*/
952 /* createIvalType - generates ival for basic types */
953 /*-----------------------------------------------------------------*/
955 createIvalType (ast * sym, sym_link * type, initList * ilist)
959 /* if initList is deep */
960 if (ilist->type == INIT_DEEP)
961 ilist = ilist->init.deep;
963 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
964 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
967 /*-----------------------------------------------------------------*/
968 /* createIvalStruct - generates initial value for structures */
969 /*-----------------------------------------------------------------*/
971 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
978 sflds = SPEC_STRUCT (type)->fields;
979 if (ilist->type != INIT_DEEP)
981 werror (E_INIT_STRUCT, "");
985 iloop = ilist->init.deep;
987 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
989 /* if we have come to end */
993 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
994 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
995 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
996 iloop, rast, rootValue)),
1002 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1003 W_EXCESS_INITIALIZERS, "struct",
1004 sym->opval.val->sym->name);
1011 /*-----------------------------------------------------------------*/
1012 /* createIvalArray - generates code for array initialization */
1013 /*-----------------------------------------------------------------*/
1015 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1019 int lcnt = 0, size = 0;
1020 literalList *literalL;
1022 /* take care of the special case */
1023 /* array of characters can be init */
1025 if (IS_CHAR (type->next))
1026 if ((rast = createIvalCharPtr (sym,
1028 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1031 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1033 /* not the special case */
1034 if (ilist->type != INIT_DEEP)
1036 werror (E_INIT_STRUCT, "");
1040 iloop = ilist->init.deep;
1041 lcnt = DCL_ELEM (type);
1043 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1047 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1049 rast = newNode(ARRAYINIT, aSym, NULL);
1050 rast->values.constlist = literalL;
1052 // Make sure size is set to length of initializer list.
1056 iloop = iloop->next;
1059 if (lcnt && size > lcnt)
1061 // Array size was specified, and we have more initializers than needed.
1062 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1063 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1072 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1073 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1074 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1075 iloop = (iloop ? iloop->next : NULL);
1081 /* no of elements given and we */
1082 /* have generated for all of them */
1085 // is this a better way? at least it won't crash
1086 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1087 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1094 /* if we have not been given a size */
1095 if (!DCL_ELEM (type))
1097 /* check, if it's a flexible array */
1098 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1099 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1101 DCL_ELEM (type) = size;
1104 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1108 /*-----------------------------------------------------------------*/
1109 /* createIvalCharPtr - generates initial values for char pointers */
1110 /*-----------------------------------------------------------------*/
1112 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1117 /* if this is a pointer & right is a literal array then */
1118 /* just assignment will do */
1119 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1120 SPEC_SCLS (iexpr->etype) == S_CODE)
1121 && IS_ARRAY (iexpr->ftype)))
1122 return newNode ('=', sym, iexpr);
1124 /* left side is an array so we have to assign each element */
1125 if ((IS_LITERAL (iexpr->etype) ||
1126 SPEC_SCLS (iexpr->etype) == S_CODE)
1127 && IS_ARRAY (iexpr->ftype))
1129 /* for each character generate an assignment */
1130 /* to the array element */
1131 char *s = SPEC_CVAL (iexpr->etype).v_char;
1133 unsigned int symsize = getSize (type);
1135 size = getSize (iexpr->ftype);
1136 if (symsize && size>symsize)
1138 if (size>(symsize+1))
1140 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1142 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1148 for (i=0;i<size;i++)
1150 rast = newNode (NULLOP,
1154 newAst_VALUE (valueFromLit ((float) i))),
1155 newAst_VALUE (valueFromLit (*s))));
1159 // now WE don't need iexpr's symbol anymore
1160 freeStringSymbol(AST_SYMBOL(iexpr));
1162 /* if we have not been given a size */
1163 if (!DCL_ELEM (type))
1165 /* check, if it's a flexible array */
1166 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1167 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1169 DCL_ELEM (type) = size;
1172 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1178 /*-----------------------------------------------------------------*/
1179 /* createIvalPtr - generates initial value for pointers */
1180 /*-----------------------------------------------------------------*/
1182 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1188 if (ilist->type == INIT_DEEP)
1189 ilist = ilist->init.deep;
1191 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1193 /* if character pointer */
1194 if (IS_CHAR (type->next))
1195 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1198 return newNode ('=', sym, iexpr);
1201 /*-----------------------------------------------------------------*/
1202 /* createIval - generates code for initial value */
1203 /*-----------------------------------------------------------------*/
1205 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1212 /* if structure then */
1213 if (IS_STRUCT (type))
1214 rast = createIvalStruct (sym, type, ilist, rootValue);
1216 /* if this is a pointer */
1218 rast = createIvalPtr (sym, type, ilist, rootValue);
1220 /* if this is an array */
1221 if (IS_ARRAY (type))
1222 rast = createIvalArray (sym, type, ilist, rootValue);
1224 /* if type is SPECIFIER */
1226 rast = createIvalType (sym, type, ilist);
1229 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1231 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1234 /*-----------------------------------------------------------------*/
1235 /* initAggregates - initialises aggregate variables with initv */
1236 /*-----------------------------------------------------------------*/
1237 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1238 ast *newAst = newAst_VALUE (symbolVal (sym));
1239 return createIval (newAst, sym->type, ival, wid, newAst);
1242 /*-----------------------------------------------------------------*/
1243 /* gatherAutoInit - creates assignment expressions for initial */
1245 /*-----------------------------------------------------------------*/
1247 gatherAutoInit (symbol * autoChain)
1254 for (sym = autoChain; sym; sym = sym->next)
1257 /* resolve the symbols in the ival */
1259 resolveIvalSym (sym->ival, sym->type);
1262 /* if we are PIC16 port,
1263 * and this is a static,
1264 * and have initial value,
1265 * and not S_CODE, don't emit in gs segment,
1266 * but allow glue.c:pic16emitRegularMap to put symbol
1267 * in idata section */
1268 if(TARGET_IS_PIC16 &&
1269 IS_STATIC (sym->etype) && sym->ival
1270 && SPEC_SCLS(sym->etype) != S_CODE) {
1271 SPEC_SCLS (sym->etype) = S_DATA;
1276 /* if this is a static variable & has an */
1277 /* initial value the code needs to be lifted */
1278 /* here to the main portion since they can be */
1279 /* initialised only once at the start */
1280 if (IS_STATIC (sym->etype) && sym->ival &&
1281 SPEC_SCLS (sym->etype) != S_CODE)
1285 /* insert the symbol into the symbol table */
1286 /* with level = 0 & name = rname */
1287 newSym = copySymbol (sym);
1288 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1290 /* now lift the code to main */
1291 if (IS_AGGREGATE (sym->type)) {
1292 work = initAggregates (sym, sym->ival, NULL);
1294 if (getNelements(sym->type, sym->ival)>1) {
1295 werrorfl (sym->fileDef, sym->lineDef,
1296 W_EXCESS_INITIALIZERS, "scalar",
1299 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1300 list2expr (sym->ival));
1303 setAstFileLine (work, sym->fileDef, sym->lineDef);
1307 staticAutos = newNode (NULLOP, staticAutos, work);
1314 /* if there is an initial value */
1315 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1317 initList *ilist=sym->ival;
1319 while (ilist->type == INIT_DEEP) {
1320 ilist = ilist->init.deep;
1323 /* update lineno for error msg */
1324 filename = sym->fileDef;
1325 lineno = sym->lineDef;
1326 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1328 if (IS_AGGREGATE (sym->type)) {
1329 work = initAggregates (sym, sym->ival, NULL);
1331 if (getNelements(sym->type, sym->ival)>1) {
1332 werrorfl (sym->fileDef, sym->lineDef,
1333 W_EXCESS_INITIALIZERS, "scalar",
1336 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1337 list2expr (sym->ival));
1341 setAstFileLine (work, sym->fileDef, sym->lineDef);
1345 init = newNode (NULLOP, init, work);
1354 /*-----------------------------------------------------------------*/
1355 /* freeStringSymbol - delete a literal string if no more usage */
1356 /*-----------------------------------------------------------------*/
1357 void freeStringSymbol(symbol *sym) {
1358 /* make sure this is a literal string */
1359 assert (sym->isstrlit);
1360 if (--sym->isstrlit == 0) { // lower the usage count
1361 memmap *segment=SPEC_OCLS(sym->etype);
1363 deleteSetItem(&segment->syms, sym);
1368 /*-----------------------------------------------------------------*/
1369 /* stringToSymbol - creates a symbol from a literal string */
1370 /*-----------------------------------------------------------------*/
1372 stringToSymbol (value * val)
1374 char name[SDCC_NAME_MAX + 1];
1375 static int charLbl = 0;
1380 // have we heard this before?
1381 for (sp = statsg->syms; sp; sp = sp->next)
1384 size = getSize (sym->type);
1385 if (sym->isstrlit && size == getSize (val->type) &&
1386 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1388 // yes, this is old news. Don't publish it again.
1389 sym->isstrlit++; // but raise the usage count
1390 return symbolVal (sym);
1394 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1395 sym = newSymbol (name, 0); /* make it @ level 0 */
1396 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1398 /* copy the type from the value passed */
1399 sym->type = copyLinkChain (val->type);
1400 sym->etype = getSpec (sym->type);
1401 /* change to storage class & output class */
1402 SPEC_SCLS (sym->etype) = S_CODE;
1403 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1404 SPEC_STAT (sym->etype) = 1;
1405 /* make the level & block = 0 */
1406 sym->block = sym->level = 0;
1408 /* create an ival */
1409 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1414 allocVariables (sym);
1417 return symbolVal (sym);
1421 /*-----------------------------------------------------------------*/
1422 /* processBlockVars - will go thru the ast looking for block if */
1423 /* a block is found then will allocate the syms */
1424 /* will also gather the auto inits present */
1425 /*-----------------------------------------------------------------*/
1427 processBlockVars (ast * tree, int *stack, int action)
1432 /* if this is a block */
1433 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1437 if (action == ALLOCATE)
1439 *stack += allocVariables (tree->values.sym);
1440 autoInit = gatherAutoInit (tree->values.sym);
1442 /* if there are auto inits then do them */
1444 tree->left = newNode (NULLOP, autoInit, tree->left);
1446 else /* action is deallocate */
1447 deallocLocal (tree->values.sym);
1450 processBlockVars (tree->left, stack, action);
1451 processBlockVars (tree->right, stack, action);
1456 /*-------------------------------------------------------------*/
1457 /* constExprTree - returns TRUE if this tree is a constant */
1459 /*-------------------------------------------------------------*/
1460 bool constExprTree (ast *cexpr) {
1466 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1468 switch (cexpr->type)
1471 if (IS_AST_LIT_VALUE(cexpr)) {
1472 // this is a literal
1475 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1476 // a function's address will never change
1479 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1480 // an array's address will never change
1483 if (IS_AST_SYM_VALUE(cexpr) &&
1484 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1485 // a symbol in code space will never change
1486 // This is only for the 'char *s="hallo"' case and will have to leave
1487 //printf(" code space symbol");
1492 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1493 "unexpected link in expression tree\n");
1496 if (cexpr->opval.op==ARRAYINIT) {
1497 // this is a list of literals
1500 if (cexpr->opval.op=='=') {
1501 return constExprTree(cexpr->right);
1503 if (cexpr->opval.op==CAST) {
1504 // cast ignored, maybe we should throw a warning here?
1505 return constExprTree(cexpr->right);
1507 if (cexpr->opval.op=='&') {
1510 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1513 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1518 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1523 /*-----------------------------------------------------------------*/
1524 /* constExprValue - returns the value of a constant expression */
1525 /* or NULL if it is not a constant expression */
1526 /*-----------------------------------------------------------------*/
1528 constExprValue (ast * cexpr, int check)
1530 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1532 /* if this is not a constant then */
1533 if (!IS_LITERAL (cexpr->ftype))
1535 /* then check if this is a literal array
1537 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1538 SPEC_CVAL (cexpr->etype).v_char &&
1539 IS_ARRAY (cexpr->ftype))
1541 value *val = valFromType (cexpr->ftype);
1542 SPEC_SCLS (val->etype) = S_LITERAL;
1543 val->sym = cexpr->opval.val->sym;
1544 val->sym->type = copyLinkChain (cexpr->ftype);
1545 val->sym->etype = getSpec (val->sym->type);
1546 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1550 /* if we are casting a literal value then */
1551 if (IS_AST_OP (cexpr) &&
1552 cexpr->opval.op == CAST &&
1553 IS_LITERAL (cexpr->right->ftype))
1555 return valCastLiteral (cexpr->ftype,
1556 floatFromVal (cexpr->right->opval.val));
1559 if (IS_AST_VALUE (cexpr))
1561 return cexpr->opval.val;
1565 werror (E_CONST_EXPECTED, "found expression");
1570 /* return the value */
1571 if (IS_AST_VALUE (cexpr))
1573 return cexpr->opval.val;
1578 /*-----------------------------------------------------------------*/
1579 /* isLabelInAst - will return true if a given label is found */
1580 /*-----------------------------------------------------------------*/
1582 isLabelInAst (symbol * label, ast * tree)
1584 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1587 if (IS_AST_OP (tree) &&
1588 tree->opval.op == LABEL &&
1589 isSymbolEqual (AST_SYMBOL (tree->left), label))
1592 return isLabelInAst (label, tree->right) &&
1593 isLabelInAst (label, tree->left);
1596 /*-----------------------------------------------------------------*/
1597 /* isLoopCountable - return true if the loop count can be determi- */
1598 /* -ned at compile time . */
1599 /*-----------------------------------------------------------------*/
1601 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1602 symbol ** sym, ast ** init, ast ** end)
1605 /* the loop is considered countable if the following
1606 conditions are true :-
1608 a) initExpr :- <sym> = <const>
1609 b) condExpr :- <sym> < <const1>
1610 c) loopExpr :- <sym> ++
1613 /* first check the initExpr */
1614 if (IS_AST_OP (initExpr) &&
1615 initExpr->opval.op == '=' && /* is assignment */
1616 IS_AST_SYM_VALUE (initExpr->left))
1617 { /* left is a symbol */
1619 *sym = AST_SYMBOL (initExpr->left);
1620 *init = initExpr->right;
1625 /* don't reverse loop with volatile counter */
1626 if (IS_VOLATILE ((*sym)->type))
1629 /* for now the symbol has to be of
1631 if (!IS_INTEGRAL ((*sym)->type))
1634 /* now check condExpr */
1635 if (IS_AST_OP (condExpr))
1638 switch (condExpr->opval.op)
1641 if (IS_AST_SYM_VALUE (condExpr->left) &&
1642 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1643 IS_AST_LIT_VALUE (condExpr->right))
1645 *end = condExpr->right;
1651 if (IS_AST_OP (condExpr->left) &&
1652 condExpr->left->opval.op == '>' &&
1653 IS_AST_LIT_VALUE (condExpr->left->right) &&
1654 IS_AST_SYM_VALUE (condExpr->left->left) &&
1655 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1658 *end = newNode ('+', condExpr->left->right,
1659 newAst_VALUE (constCharVal (1)));
1672 /* check loop expression is of the form <sym>++ */
1673 if (!IS_AST_OP (loopExpr))
1676 /* check if <sym> ++ */
1677 if (loopExpr->opval.op == INC_OP)
1683 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1684 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1691 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1692 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1700 if (loopExpr->opval.op == ADD_ASSIGN)
1703 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1704 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1705 IS_AST_LIT_VALUE (loopExpr->right) &&
1706 AST_ULONG_VALUE (loopExpr->right) != 1)
1714 /*-----------------------------------------------------------------*/
1715 /* astHasVolatile - returns true if ast contains any volatile */
1716 /*-----------------------------------------------------------------*/
1718 astHasVolatile (ast * tree)
1723 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1726 if (IS_AST_OP (tree))
1727 return astHasVolatile (tree->left) ||
1728 astHasVolatile (tree->right);
1733 /*-----------------------------------------------------------------*/
1734 /* astHasPointer - return true if the ast contains any ptr variable */
1735 /*-----------------------------------------------------------------*/
1737 astHasPointer (ast * tree)
1742 if (IS_AST_LINK (tree))
1745 /* if we hit an array expression then check
1746 only the left side */
1747 if (IS_AST_OP (tree) && tree->opval.op == '[')
1748 return astHasPointer (tree->left);
1750 if (IS_AST_VALUE (tree))
1751 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1753 return astHasPointer (tree->left) ||
1754 astHasPointer (tree->right);
1758 /*-----------------------------------------------------------------*/
1759 /* astHasSymbol - return true if the ast has the given symbol */
1760 /*-----------------------------------------------------------------*/
1762 astHasSymbol (ast * tree, symbol * sym)
1764 if (!tree || IS_AST_LINK (tree))
1767 if (IS_AST_VALUE (tree))
1769 if (IS_AST_SYM_VALUE (tree))
1770 return isSymbolEqual (AST_SYMBOL (tree), sym);
1775 return astHasSymbol (tree->left, sym) ||
1776 astHasSymbol (tree->right, sym);
1779 /*-----------------------------------------------------------------*/
1780 /* astHasDeref - return true if the ast has an indirect access */
1781 /*-----------------------------------------------------------------*/
1783 astHasDeref (ast * tree)
1785 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1788 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1790 return astHasDeref (tree->left) || astHasDeref (tree->right);
1793 /*-----------------------------------------------------------------*/
1794 /* isConformingBody - the loop body has to conform to a set of rules */
1795 /* for the loop to be considered reversible read on for rules */
1796 /*-----------------------------------------------------------------*/
1798 isConformingBody (ast * pbody, symbol * sym, ast * body)
1801 /* we are going to do a pre-order traversal of the
1802 tree && check for the following conditions. (essentially
1803 a set of very shallow tests )
1804 a) the sym passed does not participate in
1805 any arithmetic operation
1806 b) There are no function calls
1807 c) all jumps are within the body
1808 d) address of loop control variable not taken
1809 e) if an assignment has a pointer on the
1810 left hand side make sure right does not have
1811 loop control variable */
1813 /* if we reach the end or a leaf then true */
1814 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1817 /* if anything else is "volatile" */
1818 if (IS_VOLATILE (TETYPE (pbody)))
1821 /* we will walk the body in a pre-order traversal for
1823 switch (pbody->opval.op)
1825 /*------------------------------------------------------------------*/
1827 // if the loopvar is used as an index
1828 /* array op is commutative -- must check both left & right */
1829 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1832 return isConformingBody (pbody->right, sym, body)
1833 && isConformingBody (pbody->left, sym, body);
1835 /*------------------------------------------------------------------*/
1840 /*------------------------------------------------------------------*/
1844 /* sure we are not sym is not modified */
1846 IS_AST_SYM_VALUE (pbody->left) &&
1847 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1851 IS_AST_SYM_VALUE (pbody->right) &&
1852 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1857 /*------------------------------------------------------------------*/
1859 case '*': /* can be unary : if right is null then unary operation */
1864 /* if right is NULL then unary operation */
1865 /*------------------------------------------------------------------*/
1866 /*----------------------------*/
1868 /*----------------------------*/
1871 if (IS_AST_SYM_VALUE (pbody->left) &&
1872 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1875 return isConformingBody (pbody->left, sym, body);
1879 if (astHasSymbol (pbody->left, sym) ||
1880 astHasSymbol (pbody->right, sym))
1885 /*------------------------------------------------------------------*/
1896 if (IS_AST_SYM_VALUE (pbody->left) &&
1897 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1900 if (IS_AST_SYM_VALUE (pbody->right) &&
1901 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1904 return isConformingBody (pbody->left, sym, body) &&
1905 isConformingBody (pbody->right, sym, body);
1913 if (IS_AST_SYM_VALUE (pbody->left) &&
1914 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1916 return isConformingBody (pbody->left, sym, body);
1918 /*------------------------------------------------------------------*/
1930 case SIZEOF: /* evaluate wihout code generation */
1932 if (IS_AST_SYM_VALUE (pbody->left) &&
1933 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1936 if (IS_AST_SYM_VALUE (pbody->right) &&
1937 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1940 return isConformingBody (pbody->left, sym, body) &&
1941 isConformingBody (pbody->right, sym, body);
1943 /*------------------------------------------------------------------*/
1946 /* if left has a pointer & right has loop
1947 control variable then we cannot */
1948 if (astHasPointer (pbody->left) &&
1949 astHasSymbol (pbody->right, sym))
1951 if (astHasVolatile (pbody->left))
1954 if (IS_AST_SYM_VALUE (pbody->left)) {
1955 // if the loopvar has an assignment
1956 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1958 // if the loopvar is used in another (maybe conditional) block
1959 if (astHasSymbol (pbody->right, sym) &&
1960 (pbody->level >= body->level)) {
1965 if (astHasVolatile (pbody->left))
1968 if (astHasDeref(pbody->right)) return FALSE;
1970 return isConformingBody (pbody->left, sym, body) &&
1971 isConformingBody (pbody->right, sym, body);
1982 assert ("Parser should not have generated this\n");
1984 /*------------------------------------------------------------------*/
1985 /*----------------------------*/
1986 /* comma operator */
1987 /*----------------------------*/
1989 return isConformingBody (pbody->left, sym, body) &&
1990 isConformingBody (pbody->right, sym, body);
1992 /*------------------------------------------------------------------*/
1993 /*----------------------------*/
1995 /*----------------------------*/
1997 /* if local & not passed as paramater then ok */
1998 if (sym->level && !astHasSymbol(pbody->right,sym))
2002 /*------------------------------------------------------------------*/
2003 /*----------------------------*/
2004 /* return statement */
2005 /*----------------------------*/
2010 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2015 if (astHasSymbol (pbody->left, sym))
2022 return isConformingBody (pbody->left, sym, body) &&
2023 isConformingBody (pbody->right, sym, body);
2029 /*-----------------------------------------------------------------*/
2030 /* isLoopReversible - takes a for loop as input && returns true */
2031 /* if the for loop is reversible. If yes will set the value of */
2032 /* the loop control var & init value & termination value */
2033 /*-----------------------------------------------------------------*/
2035 isLoopReversible (ast * loop, symbol ** loopCntrl,
2036 ast ** init, ast ** end)
2038 /* if option says don't do it then don't */
2039 if (optimize.noLoopReverse)
2041 /* there are several tests to determine this */
2043 /* for loop has to be of the form
2044 for ( <sym> = <const1> ;
2045 [<sym> < <const2>] ;
2046 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2048 if (!isLoopCountable (AST_FOR (loop, initExpr),
2049 AST_FOR (loop, condExpr),
2050 AST_FOR (loop, loopExpr),
2051 loopCntrl, init, end))
2054 /* now do some serious checking on the body of the loop
2057 return isConformingBody (loop->left, *loopCntrl, loop->left);
2061 /*-----------------------------------------------------------------*/
2062 /* replLoopSym - replace the loop sym by loop sym -1 */
2063 /*-----------------------------------------------------------------*/
2065 replLoopSym (ast * body, symbol * sym)
2068 if (!body || IS_AST_LINK (body))
2071 if (IS_AST_SYM_VALUE (body))
2074 if (isSymbolEqual (AST_SYMBOL (body), sym))
2078 body->opval.op = '-';
2079 body->left = newAst_VALUE (symbolVal (sym));
2080 body->right = newAst_VALUE (constCharVal (1));
2088 replLoopSym (body->left, sym);
2089 replLoopSym (body->right, sym);
2093 /*-----------------------------------------------------------------*/
2094 /* reverseLoop - do the actual loop reversal */
2095 /*-----------------------------------------------------------------*/
2097 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2101 /* create the following tree
2106 if (sym) goto for_continue ;
2109 /* put it together piece by piece */
2110 rloop = newNode (NULLOP,
2111 createIf (newAst_VALUE (symbolVal (sym)),
2113 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2116 newAst_VALUE (symbolVal (sym)),
2119 replLoopSym (loop->left, sym);
2120 setAstFileLine (rloop, init->filename, init->lineno);
2122 rloop = newNode (NULLOP,
2124 newAst_VALUE (symbolVal (sym)),
2125 newNode ('-', end, init)),
2126 createLabel (AST_FOR (loop, continueLabel),
2130 newNode (SUB_ASSIGN,
2131 newAst_VALUE (symbolVal (sym)),
2132 newAst_VALUE (constCharVal (1))),
2135 rloop->lineno=init->lineno;
2136 return decorateType (rloop, RESULT_TYPE_NONE);
2140 /*-----------------------------------------------------------------*/
2141 /* searchLitOp - search tree (*ops only) for an ast with literal */
2142 /*-----------------------------------------------------------------*/
2144 searchLitOp (ast *tree, ast **parent, const char *ops)
2148 if (tree && optimize.global_cse)
2150 /* is there a literal operand? */
2152 IS_AST_OP(tree->right) &&
2153 tree->right->right &&
2154 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2156 if (IS_LITERAL (RTYPE (tree->right)) !=
2157 IS_LITERAL (LTYPE (tree->right)))
2159 tree->right->decorated = 0;
2160 tree->decorated = 0;
2164 ret = searchLitOp (tree->right, parent, ops);
2169 IS_AST_OP(tree->left) &&
2170 tree->left->right &&
2171 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2173 if (IS_LITERAL (RTYPE (tree->left)) !=
2174 IS_LITERAL (LTYPE (tree->left)))
2176 tree->left->decorated = 0;
2177 tree->decorated = 0;
2181 ret = searchLitOp (tree->left, parent, ops);
2189 /*-----------------------------------------------------------------*/
2190 /* getResultFromType */
2191 /*-----------------------------------------------------------------*/
2193 getResultTypeFromType (sym_link *type)
2195 /* type = getSpec (type); */
2197 return RESULT_TYPE_BIT;
2198 if (IS_BITFIELD (type))
2200 int blen = SPEC_BLEN (type);
2203 return RESULT_TYPE_BIT;
2205 return RESULT_TYPE_CHAR;
2206 return RESULT_TYPE_INT;
2209 return RESULT_TYPE_CHAR;
2210 if (IS_INT (type) && !IS_LONG (type))
2211 return RESULT_TYPE_INT;
2212 return RESULT_TYPE_OTHER;
2215 /*-----------------------------------------------------------------*/
2216 /* addCast - adds casts to a type specified by RESULT_TYPE */
2217 /*-----------------------------------------------------------------*/
2219 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2222 bool upCasted = FALSE;
2226 case RESULT_TYPE_NONE:
2227 /* if thing smaller than int must be promoted to int */
2229 getSize (tree->etype) >= INTSIZE)
2230 /* promotion not necessary or already an int */
2232 /* char and bits: promote to int */
2233 newLink = newIntLink();
2236 case RESULT_TYPE_BIT:
2238 /* already an int */
2239 bitsForType (tree->etype) >= 16 ||
2240 /* bit to bit operation: don't promote, the code generators
2241 hopefully know everything about promotion rules */
2242 bitsForType (tree->etype) == 1)
2244 newLink = newIntLink();
2247 case RESULT_TYPE_CHAR:
2248 if (IS_CHAR (tree->etype) ||
2249 IS_FLOAT(tree->etype) ||
2250 IS_FIXED(tree->etype))
2252 newLink = newCharLink();
2254 case RESULT_TYPE_INT:
2256 if (getSize (tree->etype) > INTSIZE)
2258 /* warn ("Loosing significant digits"); */
2262 /* char: promote to int */
2264 getSize (tree->etype) >= INTSIZE)
2266 newLink = newIntLink();
2269 case RESULT_TYPE_IFX:
2270 case RESULT_TYPE_OTHER:
2272 /* return type is ifx, long, float: promote char to int */
2273 getSize (tree->etype) >= INTSIZE)
2275 newLink = newIntLink();
2281 tree->decorated = 0;
2282 tree = newNode (CAST, newAst_LINK (newLink), tree);
2283 tree->filename = tree->right->filename;
2284 tree->lineno = tree->right->lineno;
2285 /* keep unsigned type during cast to smaller type,
2286 but not when promoting from char to int */
2288 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2289 return decorateType (tree, resultType);
2292 /*-----------------------------------------------------------------*/
2293 /* resultTypePropagate - decides if resultType can be propagated */
2294 /*-----------------------------------------------------------------*/
2296 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2298 switch (tree->opval.op)
2315 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2316 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2317 return RESULT_TYPE_NONE;
2322 return RESULT_TYPE_NONE;
2326 return RESULT_TYPE_IFX;
2328 return RESULT_TYPE_NONE;
2332 /*-----------------------------------------------------------------*/
2333 /* getLeftResultType - gets type from left branch for propagation */
2334 /*-----------------------------------------------------------------*/
2336 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2338 switch (tree->opval.op)
2342 if (IS_PTR (LTYPE (tree)))
2343 return RESULT_TYPE_NONE;
2345 return getResultTypeFromType (LETYPE (tree));
2347 if (IS_PTR (currFunc->type->next))
2348 return RESULT_TYPE_NONE;
2350 return getResultTypeFromType (currFunc->type->next);
2352 if (!IS_ARRAY (LTYPE (tree)))
2354 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2355 return RESULT_TYPE_CHAR;
2362 /*------------------------------------------------------------------*/
2363 /* gatherImplicitVariables: assigns correct type information to */
2364 /* symbols and values created by replaceAstWithTemporary */
2365 /* and adds the symbols to the declarations list of the */
2366 /* innermost block that contains them */
2367 /*------------------------------------------------------------------*/
2369 gatherImplicitVariables (ast * tree, ast * block)
2374 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2376 /* keep track of containing scope */
2379 if (tree->type == EX_OP && tree->opval.op == '=' &&
2380 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2382 symbol *assignee = tree->left->opval.val->sym;
2384 /* special case for assignment to compiler-generated temporary variable:
2385 compute type of RHS, and set the symbol's type to match */
2386 if (assignee->type == NULL && assignee->infertype) {
2387 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2389 if (dtr != tree->right)
2392 assignee->type = copyLinkChain(TTYPE(dtr));
2393 assignee->etype = getSpec(assignee->type);
2394 SPEC_SCLS (assignee->etype) = S_AUTO;
2395 SPEC_OCLS (assignee->etype) = NULL;
2396 SPEC_EXTR (assignee->etype) = 0;
2397 SPEC_STAT (assignee->etype) = 0;
2398 SPEC_VOLATILE (assignee->etype) = 0;
2399 SPEC_ABSA (assignee->etype) = 0;
2401 wassertl(block != NULL, "implicit variable not contained in block");
2402 wassert(assignee->next == NULL);
2403 if (block != NULL) {
2404 symbol **decl = &(block->values.sym);
2407 wassert(*decl != assignee); /* should not already be in list */
2408 decl = &( (*decl)->next );
2415 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2416 tree->opval.val->type == NULL &&
2417 tree->opval.val->sym &&
2418 tree->opval.val->sym->infertype)
2420 /* fixup type of value for compiler-inferred temporary var */
2421 tree->opval.val->type = tree->opval.val->sym->type;
2422 tree->opval.val->etype = tree->opval.val->sym->etype;
2425 gatherImplicitVariables(tree->left, block);
2426 gatherImplicitVariables(tree->right, block);
2429 /*--------------------------------------------------------------------*/
2430 /* decorateType - compute type for this tree, also does type checking.*/
2431 /* This is done bottom up, since type has to flow upwards. */
2432 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2433 /* result is a char and the operand(s) are int's. */
2434 /* It also does constant folding, and parameter checking. */
2435 /*--------------------------------------------------------------------*/
2437 decorateType (ast * tree, RESULT_TYPE resultType)
2441 RESULT_TYPE resultTypeProp;
2446 /* if already has type then do nothing */
2447 if (tree->decorated)
2450 tree->decorated = 1;
2453 /* print the line */
2454 /* if not block & function */
2455 if (tree->type == EX_OP &&
2456 (tree->opval.op != FUNCTION &&
2457 tree->opval.op != BLOCK &&
2458 tree->opval.op != NULLOP))
2460 filename = tree->filename;
2461 lineno = tree->lineno;
2465 /* if any child is an error | this one is an error do nothing */
2466 if (tree->isError ||
2467 (tree->left && tree->left->isError) ||
2468 (tree->right && tree->right->isError))
2471 /*------------------------------------------------------------------*/
2472 /*----------------------------*/
2473 /* leaf has been reached */
2474 /*----------------------------*/
2475 filename = tree->filename;
2476 lineno = tree->lineno;
2477 /* if this is of type value */
2478 /* just get the type */
2479 if (tree->type == EX_VALUE)
2482 if (IS_LITERAL (tree->opval.val->etype))
2485 /* if this is a character array then declare it */
2486 if (IS_ARRAY (tree->opval.val->type))
2487 tree->opval.val = stringToSymbol (tree->opval.val);
2489 /* otherwise just copy the type information */
2490 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2494 if (tree->opval.val->sym)
2496 /* if the undefined flag is set then give error message */
2497 if (tree->opval.val->sym->undefined)
2499 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2501 TTYPE (tree) = TETYPE (tree) =
2502 tree->opval.val->type = tree->opval.val->sym->type =
2503 tree->opval.val->etype = tree->opval.val->sym->etype =
2504 copyLinkChain (INTTYPE);
2506 else if (tree->opval.val->sym->implicit)
2508 /* if implicit i.e. struct/union member then no type */
2509 TTYPE (tree) = TETYPE (tree) = NULL;
2513 /* copy the type from the value into the ast */
2514 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2516 /* and mark the symbol as referenced */
2517 tree->opval.val->sym->isref = 1;
2521 wassert(0); /* unreached: all values are literals or symbols */
2526 /* if type link for the case of cast */
2527 if (tree->type == EX_LINK)
2529 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2537 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2539 if (tree->left && tree->left->type == EX_OPERAND
2540 && (tree->left->opval.op == INC_OP
2541 || tree->left->opval.op == DEC_OP)
2542 && tree->left->left)
2544 tree->left->right = tree->left->left;
2545 tree->left->left = NULL;
2547 if (tree->right && tree->right->type == EX_OPERAND
2548 && (tree->right->opval.op == INC_OP
2549 || tree->right->opval.op == DEC_OP)
2550 && tree->right->left)
2552 tree->right->right = tree->right->left;
2553 tree->right->left = NULL;
2558 /* Before decorating the left branch we've to decide in dependence
2559 upon tree->opval.op, if resultType can be propagated */
2560 resultTypeProp = resultTypePropagate (tree, resultType);
2562 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2563 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2565 dtl = decorateType (tree->left, resultTypeProp);
2567 /* if an array node, we may need to swap branches */
2568 if (tree->opval.op == '[')
2570 /* determine which is the array & which the index */
2571 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2572 IS_INTEGRAL (LTYPE (tree)))
2574 ast *tempTree = tree->left;
2575 tree->left = tree->right;
2576 tree->right = tempTree;
2580 /* After decorating the left branch there's type information available
2581 in tree->left->?type. If the op is e.g. '=' we extract the type
2582 information from there and propagate it to the right branch. */
2583 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2585 switch (tree->opval.op)
2588 /* delay right side for '?' operator since conditional macro
2589 expansions might rely on this */
2593 /* decorate right side for CALL (parameter list) in processParms();
2594 there is resultType available */
2598 /* don't allocate string if it is a sizeof argument */
2600 dtr = decorateType (tree->right, resultTypeProp);
2604 dtr = decorateType (tree->right, resultTypeProp);
2608 /* this is to take care of situations
2609 when the tree gets rewritten */
2610 if (dtl != tree->left)
2612 if (dtr != tree->right)
2614 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2618 /* depending on type of operator do */
2620 switch (tree->opval.op)
2622 /*------------------------------------------------------------------*/
2623 /*----------------------------*/
2625 /*----------------------------*/
2628 /* first check if this is a array or a pointer */
2629 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2631 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2632 goto errorTreeReturn;
2635 /* check if the type of the idx */
2636 if (!IS_INTEGRAL (RTYPE (tree)))
2638 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2639 goto errorTreeReturn;
2642 /* if the left is an rvalue then error */
2645 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2646 goto errorTreeReturn;
2649 if (IS_LITERAL (RTYPE (tree)))
2651 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2652 int arraySize = DCL_ELEM (LTYPE (tree));
2653 if (arraySize && arrayIndex >= arraySize)
2655 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2660 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2661 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2664 /*------------------------------------------------------------------*/
2665 /*----------------------------*/
2667 /*----------------------------*/
2669 /* if this is not a structure */
2670 if (!IS_STRUCT (LTYPE (tree)))
2672 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2673 goto errorTreeReturn;
2675 TTYPE (tree) = structElemType (LTYPE (tree),
2676 (tree->right->type == EX_VALUE ?
2677 tree->right->opval.val : NULL));
2678 TETYPE (tree) = getSpec (TTYPE (tree));
2681 /*------------------------------------------------------------------*/
2682 /*----------------------------*/
2683 /* struct/union pointer */
2684 /*----------------------------*/
2686 /* if not pointer to a structure */
2687 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2689 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2690 goto errorTreeReturn;
2693 if (!IS_STRUCT (LTYPE (tree)->next))
2695 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2696 goto errorTreeReturn;
2699 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2700 (tree->right->type == EX_VALUE ?
2701 tree->right->opval.val : NULL));
2702 TETYPE (tree) = getSpec (TTYPE (tree));
2704 /* adjust the storage class */
2705 switch (DCL_TYPE(tree->left->ftype)) {
2707 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2710 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2713 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2716 SPEC_SCLS (TETYPE (tree)) = 0;
2719 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2722 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2725 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2728 SPEC_SCLS (TETYPE (tree)) = 0;
2735 /* This breaks with extern declarations, bitfields, and perhaps other */
2736 /* cases (gcse). Let's leave this optimization disabled for now and */
2737 /* ponder if there's a safe way to do this. -- EEP */
2739 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2740 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2742 /* If defined struct type at addr var
2743 then rewrite (&struct var)->member
2745 and define membertype at (addr+offsetof(struct var,member)) temp
2748 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2749 AST_SYMBOL(tree->right));
2751 sym = newSymbol(genSymName (0), 0);
2752 sym->type = TTYPE (tree);
2753 sym->etype = getSpec(sym->type);
2754 sym->lineDef = tree->lineno;
2757 SPEC_STAT (sym->etype) = 1;
2758 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2760 SPEC_ABSA(sym->etype) = 1;
2761 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2764 AST_VALUE (tree) = symbolVal(sym);
2767 tree->type = EX_VALUE;
2775 /*------------------------------------------------------------------*/
2776 /*----------------------------*/
2777 /* ++/-- operation */
2778 /*----------------------------*/
2782 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2783 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2784 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2785 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2794 /*------------------------------------------------------------------*/
2795 /*----------------------------*/
2797 /*----------------------------*/
2798 case '&': /* can be unary */
2799 /* if right is NULL then unary operation */
2800 if (tree->right) /* not an unary operation */
2803 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2805 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2806 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2807 printTypeChain (LTYPE (tree), stderr);
2808 fprintf (stderr, ",");
2809 printTypeChain (RTYPE (tree), stderr);
2810 fprintf (stderr, "\n");
2811 goto errorTreeReturn;
2814 /* if they are both literal */
2815 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2817 tree->type = EX_VALUE;
2818 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2819 valFromType (RETYPE (tree)), '&');
2821 tree->right = tree->left = NULL;
2822 TETYPE (tree) = tree->opval.val->etype;
2823 TTYPE (tree) = tree->opval.val->type;
2827 /* see if this is a GETHBIT operation if yes
2830 ast *otree = optimizeGetHbit (tree, resultType);
2833 return decorateType (otree, RESULT_TYPE_NONE);
2836 /* see if this is a GETABIT operation if yes
2839 ast *otree = optimizeGetAbit (tree, resultType);
2842 return decorateType (otree, RESULT_TYPE_NONE);
2845 /* see if this is a GETBYTE operation if yes
2848 ast *otree = optimizeGetByte (tree, resultType);
2851 return decorateType (otree, RESULT_TYPE_NONE);
2854 /* see if this is a GETWORD operation if yes
2857 ast *otree = optimizeGetWord (tree, resultType);
2860 return decorateType (otree, RESULT_TYPE_NONE);
2863 /* if left is a literal exchange left & right */
2864 if (IS_LITERAL (LTYPE (tree)))
2866 ast *tTree = tree->left;
2867 tree->left = tree->right;
2868 tree->right = tTree;
2871 /* if right is a literal and */
2872 /* we can find a 2nd literal in an and-tree then */
2873 /* rearrange the tree */
2874 if (IS_LITERAL (RTYPE (tree)))
2877 ast *litTree = searchLitOp (tree, &parent, "&");
2881 ast *tTree = litTree->left;
2882 litTree->left = tree->right;
2883 tree->right = tTree;
2884 /* both operands in litTree are literal now */
2885 decorateType (parent, resultType);
2889 LRVAL (tree) = RRVAL (tree) = 1;
2891 TTYPE (tree) = computeType (LTYPE (tree),
2895 TETYPE (tree) = getSpec (TTYPE (tree));
2900 /*------------------------------------------------------------------*/
2901 /*----------------------------*/
2903 /*----------------------------*/
2904 p = newLink (DECLARATOR);
2905 /* if bit field then error */
2906 if (IS_BITVAR (tree->left->etype))
2908 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2909 goto errorTreeReturn;
2912 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2914 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2915 goto errorTreeReturn;
2918 if (IS_FUNC (LTYPE (tree)))
2920 // this ought to be ignored
2921 return (tree->left);
2924 if (IS_LITERAL(LTYPE(tree)))
2926 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2927 goto errorTreeReturn;
2932 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2933 goto errorTreeReturn;
2936 DCL_TYPE (p) = POINTER;
2937 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2938 DCL_TYPE (p) = CPOINTER;
2939 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2940 DCL_TYPE (p) = FPOINTER;
2941 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2942 DCL_TYPE (p) = PPOINTER;
2943 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2944 DCL_TYPE (p) = IPOINTER;
2945 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2946 DCL_TYPE (p) = EEPPOINTER;
2947 else if (SPEC_OCLS(tree->left->etype))
2948 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2950 DCL_TYPE (p) = POINTER;
2952 if (IS_AST_SYM_VALUE (tree->left))
2954 AST_SYMBOL (tree->left)->addrtaken = 1;
2955 AST_SYMBOL (tree->left)->allocreq = 1;
2958 p->next = LTYPE (tree);
2960 TETYPE (tree) = getSpec (TTYPE (tree));
2965 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2966 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2968 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2969 AST_SYMBOL(tree->left->right));
2970 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2971 valueFromLit(element->offset));
2974 tree->type = EX_VALUE;
2975 tree->values.literalFromCast = 1;
2981 /*------------------------------------------------------------------*/
2982 /*----------------------------*/
2984 /*----------------------------*/
2986 /* if the rewrite succeeds then don't go any further */
2988 ast *wtree = optimizeRRCRLC (tree);
2990 return decorateType (wtree, RESULT_TYPE_NONE);
2992 wtree = optimizeSWAP (tree);
2994 return decorateType (wtree, RESULT_TYPE_NONE);
2997 /* if left is a literal exchange left & right */
2998 if (IS_LITERAL (LTYPE (tree)))
3000 ast *tTree = tree->left;
3001 tree->left = tree->right;
3002 tree->right = tTree;
3005 /* if right is a literal and */
3006 /* we can find a 2nd literal in an or-tree then */
3007 /* rearrange the tree */
3008 if (IS_LITERAL (RTYPE (tree)))
3011 ast *litTree = searchLitOp (tree, &parent, "|");
3015 ast *tTree = litTree->left;
3016 litTree->left = tree->right;
3017 tree->right = tTree;
3018 /* both operands in tTree are literal now */
3019 decorateType (parent, resultType);
3024 /*------------------------------------------------------------------*/
3025 /*----------------------------*/
3027 /*----------------------------*/
3029 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3031 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3032 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3033 printTypeChain (LTYPE (tree), stderr);
3034 fprintf (stderr, ",");
3035 printTypeChain (RTYPE (tree), stderr);
3036 fprintf (stderr, "\n");
3037 goto errorTreeReturn;
3040 /* if they are both literal then rewrite the tree */
3041 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3043 tree->type = EX_VALUE;
3044 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3045 valFromType (RETYPE (tree)),
3047 tree->right = tree->left = NULL;
3048 TETYPE (tree) = tree->opval.val->etype;
3049 TTYPE (tree) = tree->opval.val->type;
3053 /* if left is a literal exchange left & right */
3054 if (IS_LITERAL (LTYPE (tree)))
3056 ast *tTree = tree->left;
3057 tree->left = tree->right;
3058 tree->right = tTree;
3061 /* if right is a literal and */
3062 /* we can find a 2nd literal in a xor-tree then */
3063 /* rearrange the tree */
3064 if (IS_LITERAL (RTYPE (tree)) &&
3065 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3068 ast *litTree = searchLitOp (tree, &parent, "^");
3072 ast *tTree = litTree->left;
3073 litTree->left = tree->right;
3074 tree->right = tTree;
3075 /* both operands in litTree are literal now */
3076 decorateType (parent, resultType);
3080 LRVAL (tree) = RRVAL (tree) = 1;
3082 TTYPE (tree) = computeType (LTYPE (tree),
3086 TETYPE (tree) = getSpec (TTYPE (tree));
3090 /*------------------------------------------------------------------*/
3091 /*----------------------------*/
3093 /*----------------------------*/
3095 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3097 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3098 goto errorTreeReturn;
3100 /* if they are both literal then */
3101 /* rewrite the tree */
3102 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3104 tree->type = EX_VALUE;
3105 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3106 valFromType (RETYPE (tree)));
3107 tree->right = tree->left = NULL;
3108 TETYPE (tree) = getSpec (TTYPE (tree) =
3109 tree->opval.val->type);
3113 LRVAL (tree) = RRVAL (tree) = 1;
3115 TETYPE (tree) = getSpec (TTYPE (tree) =
3116 computeType (LTYPE (tree),
3121 /* if right is a literal and */
3122 /* left is also a division by a literal then */
3123 /* rearrange the tree */
3124 if (IS_LITERAL (RTYPE (tree))
3125 /* avoid infinite loop */
3126 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3129 ast *litTree = searchLitOp (tree, &parent, "/");
3132 if (IS_LITERAL (RTYPE (litTree)))
3136 litTree->right = newNode ('*',
3138 copyAst (tree->right));
3139 litTree->right->filename = tree->filename;
3140 litTree->right->lineno = tree->lineno;
3142 tree->right->opval.val = constCharVal (1);
3143 decorateType (parent, resultType);
3147 /* litTree->left is literal: no gcse possible.
3148 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3149 this would cause an infinit loop. */
3150 parent->decorated = 1;
3151 decorateType (litTree, resultType);
3158 /*------------------------------------------------------------------*/
3159 /*----------------------------*/
3161 /*----------------------------*/
3163 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3165 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3166 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3167 printTypeChain (LTYPE (tree), stderr);
3168 fprintf (stderr, ",");
3169 printTypeChain (RTYPE (tree), stderr);
3170 fprintf (stderr, "\n");
3171 goto errorTreeReturn;
3173 /* if they are both literal then */
3174 /* rewrite the tree */
3175 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3177 tree->type = EX_VALUE;
3178 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3179 valFromType (RETYPE (tree)));
3180 tree->right = tree->left = NULL;
3181 TETYPE (tree) = getSpec (TTYPE (tree) =
3182 tree->opval.val->type);
3185 LRVAL (tree) = RRVAL (tree) = 1;
3186 TETYPE (tree) = getSpec (TTYPE (tree) =
3187 computeType (LTYPE (tree),
3193 /*------------------------------------------------------------------*/
3194 /*----------------------------*/
3195 /* address dereference */
3196 /*----------------------------*/
3197 case '*': /* can be unary : if right is null then unary operation */
3200 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3202 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3203 goto errorTreeReturn;
3208 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3209 goto errorTreeReturn;
3211 if (IS_ADDRESS_OF_OP(tree->left))
3213 /* replace *&obj with obj */
3214 return tree->left->left;
3216 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3217 TETYPE (tree) = getSpec (TTYPE (tree));
3218 /* adjust the storage class */
3219 switch (DCL_TYPE(tree->left->ftype)) {
3221 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3224 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3227 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3230 SPEC_SCLS (TETYPE (tree)) = 0;
3233 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3236 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3239 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3242 SPEC_SCLS (TETYPE (tree)) = 0;
3251 /*------------------------------------------------------------------*/
3252 /*----------------------------*/
3253 /* multiplication */
3254 /*----------------------------*/
3255 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3257 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3258 goto errorTreeReturn;
3261 /* if they are both literal then */
3262 /* rewrite the tree */
3263 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3265 tree->type = EX_VALUE;
3266 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3267 valFromType (RETYPE (tree)));
3268 tree->right = tree->left = NULL;
3269 TETYPE (tree) = getSpec (TTYPE (tree) =
3270 tree->opval.val->type);
3274 /* if left is a literal exchange left & right */
3275 if (IS_LITERAL (LTYPE (tree)))
3277 ast *tTree = tree->left;
3278 tree->left = tree->right;
3279 tree->right = tTree;
3282 /* if right is a literal and */
3283 /* we can find a 2nd literal in a mul-tree then */
3284 /* rearrange the tree */
3285 if (IS_LITERAL (RTYPE (tree)))
3288 ast *litTree = searchLitOp (tree, &parent, "*");
3292 ast *tTree = litTree->left;
3293 litTree->left = tree->right;
3294 tree->right = tTree;
3295 /* both operands in litTree are literal now */
3296 decorateType (parent, resultType);
3300 LRVAL (tree) = RRVAL (tree) = 1;
3301 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3302 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3303 TETYPE (tree) = getSpec (TTYPE (tree) =
3304 computeType (LTYPE (tree),
3311 /*------------------------------------------------------------------*/
3312 /*----------------------------*/
3313 /* unary '+' operator */
3314 /*----------------------------*/
3319 if (!IS_ARITHMETIC (LTYPE (tree)))
3321 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3322 goto errorTreeReturn;
3325 /* if left is a literal then do it */
3326 if (IS_LITERAL (LTYPE (tree)))
3328 tree->type = EX_VALUE;
3329 tree->opval.val = valFromType (LETYPE (tree));
3331 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3335 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3339 /*------------------------------------------------------------------*/
3340 /*----------------------------*/
3342 /*----------------------------*/
3344 /* this is not a unary operation */
3345 /* if both pointers then problem */
3346 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3347 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3349 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3350 goto errorTreeReturn;
3353 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3354 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3356 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3357 goto errorTreeReturn;
3360 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3361 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3363 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3364 goto errorTreeReturn;
3366 /* if they are both literal then */
3367 /* rewrite the tree */
3368 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3370 tree->type = EX_VALUE;
3371 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3372 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3373 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3374 valFromType (RETYPE (tree)));
3375 tree->right = tree->left = NULL;
3376 TETYPE (tree) = getSpec (TTYPE (tree) =
3377 tree->opval.val->type);
3381 /* if the right is a pointer or left is a literal
3382 xchange left & right */
3383 if (IS_ARRAY (RTYPE (tree)) ||
3384 IS_PTR (RTYPE (tree)) ||
3385 IS_LITERAL (LTYPE (tree)))
3387 ast *tTree = tree->left;
3388 tree->left = tree->right;
3389 tree->right = tTree;
3392 /* if right is a literal and */
3393 /* left is also an addition/subtraction with a literal then */
3394 /* rearrange the tree */
3395 if (IS_LITERAL (RTYPE (tree)))
3397 ast *litTree, *parent;
3398 litTree = searchLitOp (tree, &parent, "+-");
3401 if (litTree->opval.op == '+')
3405 ast *tTree = litTree->left;
3406 litTree->left = tree->right;
3407 tree->right = tree->left;
3410 else if (litTree->opval.op == '-')
3412 if (IS_LITERAL (RTYPE (litTree)))
3416 ast *tTree = litTree->left;
3417 litTree->left = tree->right;
3418 tree->right = tTree;
3424 ast *tTree = litTree->right;
3425 litTree->right = tree->right;
3426 tree->right = tTree;
3427 litTree->opval.op = '+';
3428 tree->opval.op = '-';
3431 decorateType (parent, resultType);
3435 LRVAL (tree) = RRVAL (tree) = 1;
3436 /* if the left is a pointer */
3437 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3438 TETYPE (tree) = getSpec (TTYPE (tree) =
3442 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3443 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3444 TETYPE (tree) = getSpec (TTYPE (tree) =
3445 computeType (LTYPE (tree),
3453 /*------------------------------------------------------------------*/
3454 /*----------------------------*/
3456 /*----------------------------*/
3457 case '-': /* can be unary */
3458 /* if right is null then unary */
3462 if (!IS_ARITHMETIC (LTYPE (tree)))
3464 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3465 goto errorTreeReturn;
3468 /* if left is a literal then do it */
3469 if (IS_LITERAL (LTYPE (tree)))
3471 tree->type = EX_VALUE;
3472 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3474 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3477 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3478 TETYPE (tree) = getSpec (TTYPE (tree) =
3479 computeType (LTYPE (tree),
3487 /*------------------------------------------------------------------*/
3488 /*----------------------------*/
3490 /*----------------------------*/
3492 if (!(IS_PTR (LTYPE (tree)) ||
3493 IS_ARRAY (LTYPE (tree)) ||
3494 IS_ARITHMETIC (LTYPE (tree))))
3496 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3497 goto errorTreeReturn;
3500 if (!(IS_PTR (RTYPE (tree)) ||
3501 IS_ARRAY (RTYPE (tree)) ||
3502 IS_ARITHMETIC (RTYPE (tree))))
3504 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3505 goto errorTreeReturn;
3508 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3509 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3510 IS_INTEGRAL (RTYPE (tree))))
3512 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3513 goto errorTreeReturn;
3516 /* if they are both literal then */
3517 /* rewrite the tree */
3518 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3520 tree->type = EX_VALUE;
3521 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3522 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3523 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3524 valFromType (RETYPE (tree)));
3525 tree->right = tree->left = NULL;
3526 TETYPE (tree) = getSpec (TTYPE (tree) =
3527 tree->opval.val->type);
3531 /* if the left & right are equal then zero */
3532 if (isAstEqual (tree->left, tree->right))
3534 tree->type = EX_VALUE;
3535 tree->left = tree->right = NULL;
3536 tree->opval.val = constCharVal (0);
3537 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3541 /* if both of them are pointers or arrays then */
3542 /* the result is going to be an integer */
3543 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3544 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3545 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3547 /* if only the left is a pointer */
3548 /* then result is a pointer */
3549 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3550 TETYPE (tree) = getSpec (TTYPE (tree) =
3554 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3555 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3557 TETYPE (tree) = getSpec (TTYPE (tree) =
3558 computeType (LTYPE (tree),
3564 LRVAL (tree) = RRVAL (tree) = 1;
3566 /* if right is a literal and */
3567 /* left is also an addition/subtraction with a literal then */
3568 /* rearrange the tree */
3569 if (IS_LITERAL (RTYPE (tree))
3570 /* avoid infinite loop */
3571 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3573 ast *litTree, *litParent;
3574 litTree = searchLitOp (tree, &litParent, "+-");
3577 if (litTree->opval.op == '+')
3581 ast *tTree = litTree->left;
3582 litTree->left = litTree->right;
3583 litTree->right = tree->right;
3584 tree->right = tTree;
3585 tree->opval.op = '+';
3586 litTree->opval.op = '-';
3588 else if (litTree->opval.op == '-')
3590 if (IS_LITERAL (RTYPE (litTree)))
3594 ast *tTree = litTree->left;
3595 litTree->left = tree->right;
3596 tree->right = litParent->left;
3597 litParent->left = tTree;
3598 litTree->opval.op = '+';
3600 tree->decorated = 0;
3601 decorateType (tree, resultType);
3607 ast *tTree = litTree->right;
3608 litTree->right = tree->right;
3609 tree->right = tTree;
3612 decorateType (litParent, resultType);
3617 /*------------------------------------------------------------------*/
3618 /*----------------------------*/
3620 /*----------------------------*/
3622 /* can be only integral type */
3623 if (!IS_INTEGRAL (LTYPE (tree)))
3625 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3626 goto errorTreeReturn;
3629 /* if left is a literal then do it */
3630 if (IS_LITERAL (LTYPE (tree)))
3632 tree->type = EX_VALUE;
3633 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3635 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3636 return addCast (tree, resultTypeProp, TRUE);
3639 if (resultType == RESULT_TYPE_BIT &&
3640 IS_UNSIGNED (tree->left->etype) &&
3641 getSize (tree->left->etype) < INTSIZE)
3643 /* promotion rules are responsible for this strange result:
3644 bit -> int -> ~int -> bit
3645 uchar -> int -> ~int -> bit
3647 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3649 /* optimize bit-result, even if we optimize a buggy source */
3650 tree->type = EX_VALUE;
3651 tree->opval.val = constCharVal (1);
3654 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3656 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3659 /*------------------------------------------------------------------*/
3660 /*----------------------------*/
3662 /*----------------------------*/
3664 /* can be pointer */
3665 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3666 !IS_PTR (LTYPE (tree)) &&
3667 !IS_ARRAY (LTYPE (tree)))
3669 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3670 goto errorTreeReturn;
3673 /* if left is another '!' */
3674 if (IS_AST_NOT_OPER (tree->left))
3676 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3678 /* replace double '!!X' by 'X' */
3679 return tree->left->left;
3681 /* remove double '!!X' by 'X ? 1 : 0' */
3682 tree->opval.op = '?';
3683 tree->left = tree->left->left;
3684 tree->right = newNode (':',
3685 newAst_VALUE (constCharVal (1)),
3686 newAst_VALUE (constCharVal (0)));
3687 tree->right->filename = tree->filename;
3688 tree->right->lineno = tree->lineno;
3689 tree->decorated = 0;
3690 return decorateType (tree, resultType);
3693 /* if left is a literal then do it */
3694 if (IS_LITERAL (LTYPE (tree)))
3696 tree->type = EX_VALUE;
3697 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3699 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3703 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3706 /*------------------------------------------------------------------*/
3707 /*----------------------------*/
3709 /*----------------------------*/
3713 TTYPE (tree) = LTYPE (tree);
3714 TETYPE (tree) = LETYPE (tree);
3719 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3723 TTYPE (tree) = TETYPE (tree) = newCharLink();
3727 TTYPE (tree) = TETYPE (tree) = newIntLink();
3732 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3734 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3735 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3736 printTypeChain (LTYPE (tree), stderr);
3737 fprintf (stderr, ",");
3738 printTypeChain (RTYPE (tree), stderr);
3739 fprintf (stderr, "\n");
3740 goto errorTreeReturn;
3743 /* make smaller type only if it's a LEFT_OP */
3744 if (tree->opval.op == LEFT_OP)
3745 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3747 /* if they are both literal then */
3748 /* rewrite the tree */
3749 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3751 tree->type = EX_VALUE;
3752 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3753 valFromType (RETYPE (tree)),
3754 (tree->opval.op == LEFT_OP ? 1 : 0));
3755 tree->right = tree->left = NULL;
3756 TETYPE (tree) = getSpec (TTYPE (tree) =
3757 tree->opval.val->type);
3761 /* see if this is a GETBYTE operation if yes
3764 ast *otree = optimizeGetByte (tree, resultType);
3767 return decorateType (otree, RESULT_TYPE_NONE);
3770 /* see if this is a GETWORD operation if yes
3773 ast *otree = optimizeGetWord (tree, resultType);
3776 return decorateType (otree, RESULT_TYPE_NONE);
3779 LRVAL (tree) = RRVAL (tree) = 1;
3780 if (tree->opval.op == LEFT_OP)
3782 TETYPE (tree) = getSpec (TTYPE (tree) =
3783 computeType (LTYPE (tree),
3790 /* no promotion necessary */
3791 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3792 if (IS_LITERAL (TTYPE (tree)))
3793 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3796 /* if only the right side is a literal & we are
3797 shifting more than size of the left operand then zero */
3798 if (IS_LITERAL (RTYPE (tree)) &&
3799 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3800 (getSize (TETYPE (tree)) * 8))
3802 if (tree->opval.op==LEFT_OP ||
3803 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3805 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3806 (tree->opval.op == LEFT_OP ? "left" : "right"));
3807 tree->type = EX_VALUE;
3808 tree->left = tree->right = NULL;
3809 tree->opval.val = constCharVal (0);
3810 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3817 /*------------------------------------------------------------------*/
3818 /*----------------------------*/
3820 /*----------------------------*/
3821 case CAST: /* change the type */
3822 /* cannot cast to an aggregate type */
3823 if (IS_AGGREGATE (LTYPE (tree)))
3825 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3826 goto errorTreeReturn;
3829 /* make sure the type is complete and sane */
3830 changePointer(LTYPE(tree));
3831 checkTypeSanity(LETYPE(tree), "(cast)");
3833 /* if 'from' and 'to' are the same remove the superfluous cast, */
3834 /* this helps other optimizations */
3835 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3840 /* If code memory is read only, then pointers to code memory */
3841 /* implicitly point to constants -- make this explicit */
3843 sym_link *t = LTYPE(tree);
3844 while (t && t->next)
3846 if (IS_CODEPTR(t) && port->mem.code_ro)
3848 if (IS_SPEC(t->next))
3849 SPEC_CONST (t->next) = 1;
3851 DCL_PTR_CONST (t->next) = 1;
3858 /* if the right is a literal replace the tree */
3859 if (IS_LITERAL (RETYPE (tree))) {
3860 if (!IS_PTR (LTYPE (tree))) {
3861 tree->type = EX_VALUE;
3863 valCastLiteral (LTYPE (tree),
3864 floatFromVal (valFromType (RETYPE (tree))));
3867 TTYPE (tree) = tree->opval.val->type;
3868 tree->values.literalFromCast = 1;
3869 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3870 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3871 sym_link *rest = LTYPE(tree)->next;
3872 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3873 TTYPE(tree) = newLink(DECLARATOR);
3874 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3875 TTYPE(tree)->next = rest;
3876 tree->left->opval.lnk = TTYPE(tree);
3879 TTYPE (tree) = LTYPE (tree);
3883 TTYPE (tree) = LTYPE (tree);
3887 #if 0 // this is already checked, now this could be explicit
3888 /* if pointer to struct then check names */
3889 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3890 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3891 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3893 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3894 SPEC_STRUCT(LETYPE(tree))->tag);
3897 if (IS_ADDRESS_OF_OP(tree->right)
3898 && IS_AST_SYM_VALUE (tree->right->left)
3899 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3901 symbol * sym = AST_SYMBOL (tree->right->left);
3902 unsigned int gptype = 0;
3903 unsigned int addr = SPEC_ADDR (sym->etype);
3905 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3906 || TARGET_IS_PIC16) )
3908 switch (SPEC_SCLS (sym->etype))
3911 gptype = GPTYPE_CODE;
3914 gptype = GPTYPE_FAR;
3918 gptype = GPTYPE_NEAR;
3921 gptype = GPTYPE_XSTACK;
3926 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3927 gptype = GPTYPE_NEAR;
3929 addr |= gptype << (8*(GPTRSIZE - 1));
3932 tree->type = EX_VALUE;
3934 valCastLiteral (LTYPE (tree), addr);
3935 TTYPE (tree) = tree->opval.val->type;
3936 TETYPE (tree) = getSpec (TTYPE (tree));
3939 tree->values.literalFromCast = 1;
3943 /* handle offsetof macro: */
3944 /* #define offsetof(TYPE, MEMBER) \ */
3945 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3946 if (IS_ADDRESS_OF_OP(tree->right)
3947 && IS_AST_OP (tree->right->left)
3948 && tree->right->left->opval.op == PTR_OP
3949 && IS_AST_OP (tree->right->left->left)
3950 && tree->right->left->left->opval.op == CAST
3951 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3953 symbol *element = getStructElement (
3954 SPEC_STRUCT (LETYPE(tree->right->left)),
3955 AST_SYMBOL(tree->right->left->right)
3959 tree->type = EX_VALUE;
3960 tree->opval.val = valCastLiteral (
3963 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3966 TTYPE (tree) = tree->opval.val->type;
3967 TETYPE (tree) = getSpec (TTYPE (tree));
3974 /* if the right is a literal replace the tree */
3975 if (IS_LITERAL (RETYPE (tree))) {
3977 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3978 /* rewrite (type *)litaddr
3980 and define type at litaddr temp
3981 (but only if type's storage class is not generic)
3983 ast *newTree = newNode ('&', NULL, NULL);
3986 TTYPE (newTree) = LTYPE (tree);
3987 TETYPE (newTree) = getSpec(LTYPE (tree));
3989 /* define a global symbol at the casted address*/
3990 sym = newSymbol(genSymName (0), 0);
3991 sym->type = LTYPE (tree)->next;
3993 sym->type = newLink (V_VOID);
3994 sym->etype = getSpec(sym->type);
3995 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3996 sym->lineDef = tree->lineno;
3999 SPEC_STAT (sym->etype) = 1;
4000 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4001 SPEC_ABSA(sym->etype) = 1;
4002 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4005 newTree->left = newAst_VALUE(symbolVal(sym));
4006 newTree->left->filename = tree->filename;
4007 newTree->left->lineno = tree->lineno;
4008 LTYPE (newTree) = sym->type;
4009 LETYPE (newTree) = sym->etype;
4010 LLVAL (newTree) = 1;
4011 LRVAL (newTree) = 0;
4012 TLVAL (newTree) = 1;
4016 if (!IS_PTR (LTYPE (tree))) {
4017 tree->type = EX_VALUE;
4019 valCastLiteral (LTYPE (tree),
4020 floatFromVal (valFromType (RTYPE (tree))));
4021 TTYPE (tree) = tree->opval.val->type;
4024 tree->values.literalFromCast = 1;
4025 TETYPE (tree) = getSpec (TTYPE (tree));
4029 TTYPE (tree) = LTYPE (tree);
4033 TETYPE (tree) = getSpec (TTYPE (tree));
4037 /*------------------------------------------------------------------*/
4038 /*----------------------------*/
4039 /* logical &&, || */
4040 /*----------------------------*/
4043 /* each must be arithmetic type or be a pointer */
4044 if (!IS_PTR (LTYPE (tree)) &&
4045 !IS_ARRAY (LTYPE (tree)) &&
4046 !IS_INTEGRAL (LTYPE (tree)))
4048 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4049 goto errorTreeReturn;
4052 if (!IS_PTR (RTYPE (tree)) &&
4053 !IS_ARRAY (RTYPE (tree)) &&
4054 !IS_INTEGRAL (RTYPE (tree)))
4056 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4057 goto errorTreeReturn;
4059 /* if they are both literal then */
4060 /* rewrite the tree */
4061 if (IS_LITERAL (RTYPE (tree)) &&
4062 IS_LITERAL (LTYPE (tree)))
4064 tree->type = EX_VALUE;
4065 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4066 valFromType (RTYPE (tree)),
4068 tree->right = tree->left = NULL;
4069 TETYPE (tree) = getSpec (TTYPE (tree) =
4070 tree->opval.val->type);
4073 LRVAL (tree) = RRVAL (tree) = 1;
4074 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4077 /*------------------------------------------------------------------*/
4078 /*----------------------------*/
4079 /* comparison operators */
4080 /*----------------------------*/
4088 ast *lt = optimizeCompare (tree);
4094 /* if they are pointers they must be castable */
4095 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4097 if (tree->opval.op==EQ_OP &&
4098 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4099 // we cannot cast a gptr to a !gptr: switch the leaves
4100 struct ast *s=tree->left;
4101 tree->left=tree->right;
4104 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4106 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4107 fprintf (stderr, "comparing type ");
4108 printTypeChain (LTYPE (tree), stderr);
4109 fprintf (stderr, "to type ");
4110 printTypeChain (RTYPE (tree), stderr);
4111 fprintf (stderr, "\n");
4112 goto errorTreeReturn;
4115 /* else they should be promotable to one another */
4118 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4119 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4121 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4123 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4124 fprintf (stderr, "comparing type ");
4125 printTypeChain (LTYPE (tree), stderr);
4126 fprintf (stderr, "to type ");
4127 printTypeChain (RTYPE (tree), stderr);
4128 fprintf (stderr, "\n");
4129 goto errorTreeReturn;
4134 CCR_RESULT ccr_result = CCR_OK;
4136 /* if left is integral and right is literal
4137 then check constant range */
4138 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4139 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4140 tree->opval.op, FALSE);
4141 if (ccr_result == CCR_OK &&
4142 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4143 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4144 tree->opval.op, TRUE);
4147 case CCR_ALWAYS_TRUE:
4148 case CCR_ALWAYS_FALSE:
4149 if (!options.lessPedantic)
4150 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4151 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4152 return decorateType (newAst_VALUE (constCharVal (
4153 ccr_result == CCR_ALWAYS_TRUE ? 1 : 0)),
4161 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4162 if (tree->opval.op == '>' &&
4163 SPEC_USIGN(LETYPE(tree)) &&
4164 IS_LITERAL(RTYPE(tree)) &&
4165 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4167 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4169 /* the parent is an ifx: */
4170 /* if (unsigned value) */
4174 /* (unsigned value) ? 1 : 0 */
4175 tree->opval.op = '?';
4176 tree->right = newNode (':',
4177 newAst_VALUE (constCharVal (1)),
4178 tree->right); /* val 0 */
4179 tree->right->filename = tree->filename;
4180 tree->right->lineno = tree->lineno;
4181 tree->right->left->filename = tree->filename;
4182 tree->right->left->lineno = tree->lineno;
4183 tree->decorated = 0;
4184 return decorateType (tree, resultType);
4187 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4188 if (IS_LITERAL(RTYPE(tree)) &&
4189 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4190 tree->opval.op == EQ_OP &&
4191 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4193 tree->opval.op = '!';
4195 tree->decorated = 0;
4196 return decorateType (tree, resultType);
4199 /* if they are both literal then */
4200 /* rewrite the tree */
4201 if (IS_LITERAL (RTYPE (tree)) &&
4202 IS_LITERAL (LTYPE (tree)))
4204 tree->type = EX_VALUE;
4205 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4206 valFromType (RETYPE (tree)),
4208 tree->right = tree->left = NULL;
4209 TETYPE (tree) = getSpec (TTYPE (tree) =
4210 tree->opval.val->type);
4214 /* if one is 'signed char ' and the other one is 'unsigned char' */
4215 /* it's necessary to promote to int */
4216 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4217 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4219 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4220 if it's possible to use a 'signed char' */
4222 /* is left a 'unsigned char'? */
4223 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4224 /* the value range of a 'unsigned char' is 0...255;
4225 if the actual value is < 128 it can be changed to signed */
4226 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4228 /* now we've got 2 'signed char'! */
4229 SPEC_USIGN (RETYPE (tree)) = 0;
4231 /* same test for the left operand: */
4232 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4233 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4235 SPEC_USIGN (LETYPE (tree)) = 0;
4239 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4240 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4241 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4245 LRVAL (tree) = RRVAL (tree) = 1;
4246 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4248 /* condition transformations */
4250 unsigned transformedOp = 0;
4252 switch (tree->opval.op)
4254 case '<': /* transform (a < b) to !(a >= b) */
4256 transformedOp = GE_OP;
4258 case '>': /* transform (a > b) to !(a <= b) */
4260 transformedOp = LE_OP;
4262 case LE_OP: /* transform (a <= b) to !(a > b) */
4264 transformedOp = '>';
4266 case GE_OP: /* transform (a >= b) to !(a < b) */
4268 transformedOp = '<';
4270 case NE_OP: /* transform (a != b) to !(a == b) */
4272 transformedOp = EQ_OP;
4274 case EQ_OP: /* transform (a == b) to !(a != b) */
4276 transformedOp = NE_OP;
4283 tree->opval.op = transformedOp;
4284 tree->decorated = 0;
4285 tree = newNode ('!', tree, NULL);
4286 tree->filename = tree->left->filename;
4287 tree->lineno = tree->left->lineno;
4288 return decorateType (tree, resultType);
4294 /*------------------------------------------------------------------*/
4295 /*----------------------------*/
4297 /*----------------------------*/
4298 case SIZEOF: /* evaluate wihout code generation */
4299 /* change the type to a integer */
4301 int size = getSize (tree->right->ftype);
4303 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4304 if (!size && !IS_VOID(tree->right->ftype))
4305 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4307 tree->type = EX_VALUE;
4308 tree->opval.val = constVal (buffer);
4309 tree->right = tree->left = NULL;
4310 TETYPE (tree) = getSpec (TTYPE (tree) =
4311 tree->opval.val->type);
4315 /*------------------------------------------------------------------*/
4316 /*----------------------------*/
4318 /*----------------------------*/
4320 /* return typeof enum value */
4321 tree->type = EX_VALUE;
4324 if (IS_SPEC(tree->right->ftype)) {
4325 switch (SPEC_NOUN(tree->right->ftype)) {
4327 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4328 else typeofv = TYPEOF_INT;
4331 typeofv = TYPEOF_FLOAT;
4334 typeofv = TYPEOF_FIXED16X16;
4337 typeofv = TYPEOF_CHAR;
4340 typeofv = TYPEOF_VOID;
4343 typeofv = TYPEOF_STRUCT;
4346 typeofv = TYPEOF_BITFIELD;
4349 typeofv = TYPEOF_BIT;
4352 typeofv = TYPEOF_SBIT;
4358 switch (DCL_TYPE(tree->right->ftype)) {
4360 typeofv = TYPEOF_POINTER;
4363 typeofv = TYPEOF_FPOINTER;
4366 typeofv = TYPEOF_CPOINTER;
4369 typeofv = TYPEOF_GPOINTER;
4372 typeofv = TYPEOF_PPOINTER;
4375 typeofv = TYPEOF_IPOINTER;
4378 typeofv = TYPEOF_ARRAY;
4381 typeofv = TYPEOF_FUNCTION;
4387 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4388 tree->opval.val = constVal (buffer);
4389 tree->right = tree->left = NULL;
4390 TETYPE (tree) = getSpec (TTYPE (tree) =
4391 tree->opval.val->type);
4394 /*------------------------------------------------------------------*/
4395 /*----------------------------*/
4396 /* conditional operator '?' */
4397 /*----------------------------*/
4399 /* the type is value of the colon operator (on the right) */
4400 assert (IS_COLON_OP (tree->right));
4402 /* If already known then replace the tree : optimizer will do it
4403 but faster to do it here. If done before decorating tree->right
4404 this can save generating unused const strings. */
4405 if (IS_LITERAL (LTYPE (tree)))
4407 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4408 return decorateType (tree->right->left, resultTypeProp);
4410 return decorateType (tree->right->right, resultTypeProp);
4413 tree->right = decorateType (tree->right, resultTypeProp);
4415 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4416 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4418 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4419 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4421 if ((valTrue != 0) && (valFalse == 0))
4423 /* assign cond to result */
4424 tree->left->decorated = 0;
4425 return decorateType (tree->left, resultTypeProp);
4427 else if ((valTrue == 0) && (valFalse != 0))
4429 /* assign !cond to result */
4430 tree->opval.op = '!';
4431 tree->decorated = 0;
4433 return decorateType (tree, resultTypeProp);
4437 /* they have the same boolean value, make them equal */
4438 tree->right->left = tree->right->right;
4442 /* if they are equal then replace the tree */
4443 if (isAstEqual (tree->right->left, tree->right->right))
4445 return tree->right->left;
4448 TTYPE (tree) = RTYPE (tree);
4449 TETYPE (tree) = getSpec (TTYPE (tree));
4453 /* if they don't match we have a problem */
4454 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4455 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4457 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4458 goto errorTreeReturn;
4461 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4462 resultType, tree->opval.op);
4463 TETYPE (tree) = getSpec (TTYPE (tree));
4467 #if 0 // assignment operators are converted by the parser
4468 /*------------------------------------------------------------------*/
4469 /*----------------------------*/
4470 /* assignment operators */
4471 /*----------------------------*/
4474 /* for these it must be both must be integral */
4475 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4476 !IS_ARITHMETIC (RTYPE (tree)))
4478 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4479 goto errorTreeReturn;
4482 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4484 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4485 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4489 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4490 goto errorTreeReturn;
4501 /* for these it must be both must be integral */
4502 if (!IS_INTEGRAL (LTYPE (tree)) ||
4503 !IS_INTEGRAL (RTYPE (tree)))
4505 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4506 goto errorTreeReturn;
4509 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4511 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4512 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4516 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4517 goto errorTreeReturn;
4523 /*------------------------------------------------------------------*/
4524 /*----------------------------*/
4526 /*----------------------------*/
4528 if (!(IS_PTR (LTYPE (tree)) ||
4529 IS_ARITHMETIC (LTYPE (tree))))
4531 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4532 goto errorTreeReturn;
4535 if (!(IS_PTR (RTYPE (tree)) ||
4536 IS_ARITHMETIC (RTYPE (tree))))
4538 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4539 goto errorTreeReturn;
4542 TETYPE (tree) = getSpec (TTYPE (tree) =
4543 computeType (LTYPE (tree),
4548 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4549 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4553 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4554 goto errorTreeReturn;
4560 /*------------------------------------------------------------------*/
4561 /*----------------------------*/
4563 /*----------------------------*/
4565 /* this is not a unary operation */
4566 /* if both pointers then problem */
4567 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4569 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4570 goto errorTreeReturn;
4573 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4575 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4576 goto errorTreeReturn;
4579 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4581 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4582 goto errorTreeReturn;
4585 TETYPE (tree) = getSpec (TTYPE (tree) =
4586 computeType (LTYPE (tree),
4591 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4592 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4596 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4597 goto errorTreeReturn;
4600 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4601 tree->opval.op = '=';
4606 /*------------------------------------------------------------------*/
4607 /*----------------------------*/
4608 /* straight assignemnt */
4609 /*----------------------------*/
4611 /* cannot be an aggregate */
4612 if (IS_AGGREGATE (LTYPE (tree)))
4614 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4615 goto errorTreeReturn;
4618 /* they should either match or be castable */
4619 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4621 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4622 printFromToType(RTYPE(tree),LTYPE(tree));
4625 /* if the left side of the tree is of type void
4626 then report error */
4627 if (IS_VOID (LTYPE (tree)))
4629 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4630 printFromToType(RTYPE(tree), LTYPE(tree));
4633 TETYPE (tree) = getSpec (TTYPE (tree) =
4637 if (!tree->initMode ) {
4638 if (IS_CONSTANT(LTYPE(tree)))
4639 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4643 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4644 goto errorTreeReturn;
4649 /*------------------------------------------------------------------*/
4650 /*----------------------------*/
4651 /* comma operator */
4652 /*----------------------------*/
4654 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4657 /*------------------------------------------------------------------*/
4658 /*----------------------------*/
4660 /*----------------------------*/
4663 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4664 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4666 if (tree->left->opval.op == '*' && !tree->left->right)
4667 tree->left = tree->left->left;
4670 /* require a function or pointer to function */
4671 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4673 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4674 goto errorTreeReturn;
4677 /* if there are parms, make sure that
4678 parms are decorate / process / reverse only once */
4680 !tree->right->decorated)
4685 if (IS_FUNCPTR (LTYPE (tree)))
4687 functype = LTYPE (tree)->next;
4688 processFuncPtrArgs (functype);
4691 functype = LTYPE (tree);
4693 if (processParms (tree->left, FUNC_ARGS(functype),
4694 &tree->right, &parmNumber, TRUE))
4696 goto errorTreeReturn;
4699 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4700 !IFFUNC_ISBUILTIN(functype))
4702 reverseParms (tree->right);
4705 TTYPE (tree) = functype->next;
4706 TETYPE (tree) = getSpec (TTYPE (tree));
4710 /*------------------------------------------------------------------*/
4711 /*----------------------------*/
4712 /* return statement */
4713 /*----------------------------*/
4718 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4720 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4721 printFromToType (RTYPE(tree), currFunc->type->next);
4722 goto errorTreeReturn;
4725 if (IS_VOID (currFunc->type->next)
4727 !IS_VOID (RTYPE (tree)))
4729 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4730 goto errorTreeReturn;
4733 /* if there is going to be a casting required then add it */
4734 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4737 decorateType (newNode (CAST,
4738 newAst_LINK (copyLinkChain (currFunc->type->next)),
4748 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4750 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4751 goto errorTreeReturn;
4754 TTYPE (tree) = TETYPE (tree) = NULL;
4757 /*------------------------------------------------------------------*/
4758 /*----------------------------*/
4759 /* switch statement */
4760 /*----------------------------*/
4762 /* the switch value must be an integer */
4763 if (!IS_INTEGRAL (LTYPE (tree)))
4765 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4766 goto errorTreeReturn;
4769 TTYPE (tree) = TETYPE (tree) = NULL;
4772 /*------------------------------------------------------------------*/
4773 /*----------------------------*/
4775 /*----------------------------*/
4777 tree->left = backPatchLabels (tree->left,
4780 TTYPE (tree) = TETYPE (tree) = NULL;
4783 /*------------------------------------------------------------------*/
4784 /*----------------------------*/
4786 /*----------------------------*/
4789 AST_FOR (tree, initExpr) = decorateType (
4790 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4791 AST_FOR (tree, condExpr) = decorateType (
4792 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4793 AST_FOR (tree, loopExpr) = decorateType (
4794 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4796 /* if the for loop is reversible then
4797 reverse it otherwise do what we normally
4803 if (isLoopReversible (tree, &sym, &init, &end))
4804 return reverseLoop (tree, sym, init, end);
4806 return decorateType (createFor (AST_FOR (tree, trueLabel),
4807 AST_FOR (tree, continueLabel),
4808 AST_FOR (tree, falseLabel),
4809 AST_FOR (tree, condLabel),
4810 AST_FOR (tree, initExpr),
4811 AST_FOR (tree, condExpr),
4812 AST_FOR (tree, loopExpr),
4813 tree->left), RESULT_TYPE_NONE);
4816 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4817 "node PARAM shouldn't be processed here");
4818 /* but in processParams() */
4821 TTYPE (tree) = TETYPE (tree) = NULL;
4825 /* some error found this tree will be killed */
4827 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4828 tree->opval.op = NULLOP;
4834 /*-----------------------------------------------------------------*/
4835 /* sizeofOp - processes size of operation */
4836 /*-----------------------------------------------------------------*/
4838 sizeofOp (sym_link * type)
4843 /* make sure the type is complete and sane */
4844 checkTypeSanity(type, "(sizeof)");
4846 /* get the size and convert it to character */
4847 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4848 if (!size && !IS_VOID(type))
4849 werror (E_SIZEOF_INCOMPLETE_TYPE);
4851 /* now convert into value */
4852 return constVal (buff);
4856 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4857 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4858 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4859 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4860 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4861 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4862 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4864 /*-----------------------------------------------------------------*/
4865 /* backPatchLabels - change and or not operators to flow control */
4866 /*-----------------------------------------------------------------*/
4868 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4874 /* while-loops insert a label between the IFX and the condition,
4875 therefore look behind the label too */
4876 if (tree->opval.op == LABEL &&
4878 IS_ANDORNOT (tree->right))
4880 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4884 if (!(IS_ANDORNOT (tree)))
4887 /* if this an and */
4890 static int localLbl = 0;
4893 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4894 localLabel = newSymbol (buffer, NestLevel);
4896 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4898 /* if left is already a IFX then just change the if true label in that */
4899 if (!IS_IFX (tree->left))
4900 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4902 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4903 /* right is a IFX then just join */
4904 if (IS_IFX (tree->right))
4905 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4907 tree->right = createLabel (localLabel, tree->right);
4908 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4910 return newNode (NULLOP, tree->left, tree->right);
4913 /* if this is an or operation */
4916 static int localLbl = 0;
4919 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4920 localLabel = newSymbol (buffer, NestLevel);
4922 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4924 /* if left is already a IFX then just change the if true label in that */
4925 if (!IS_IFX (tree->left))
4926 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4928 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4929 /* right is a IFX then just join */
4930 if (IS_IFX (tree->right))
4931 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4933 tree->right = createLabel (localLabel, tree->right);
4934 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4936 return newNode (NULLOP, tree->left, tree->right);
4942 /* call with exchanged labels */
4943 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4945 /* if left isn't already a IFX */
4946 if (!IS_IFX (tree->left))
4948 tree->left = newNode (IFX, tree->left, NULL);
4949 tree->left->trueLabel = falseLabel;
4950 tree->left->falseLabel = trueLabel;
4957 tree->trueLabel = trueLabel;
4958 tree->falseLabel = falseLabel;
4965 /*-----------------------------------------------------------------*/
4966 /* createBlock - create expression tree for block */
4967 /*-----------------------------------------------------------------*/
4969 createBlock (symbol * decl, ast * body)
4973 /* if the block has nothing */
4977 ex = newNode (BLOCK, NULL, body);
4978 ex->values.sym = decl;
4981 ex->filename = NULL;
4986 /*-----------------------------------------------------------------*/
4987 /* createLabel - creates the expression tree for labels */
4988 /*-----------------------------------------------------------------*/
4990 createLabel (symbol * label, ast * stmnt)
4993 char name[SDCC_NAME_MAX + 1];
4996 /* must create fresh symbol if the symbol name */
4997 /* exists in the symbol table, since there can */
4998 /* be a variable with the same name as the labl */
4999 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5000 (csym->level == label->level))
5001 label = newSymbol (label->name, label->level);
5003 /* change the name before putting it in add _ */
5004 SNPRINTF(name, sizeof(name), "%s", label->name);
5006 /* put the label in the LabelSymbol table */
5007 /* but first check if a label of the same */
5009 if ((csym = findSym (LabelTab, NULL, name)))
5010 werror (E_DUPLICATE_LABEL, label->name);
5012 addSym (LabelTab, label, name, label->level, 0, 0);
5016 label->key = labelKey++;
5017 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5018 rValue->filename = NULL;
5024 /*-----------------------------------------------------------------*/
5025 /* createCase - generates the parsetree for a case statement */
5026 /*-----------------------------------------------------------------*/
5028 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5030 char caseLbl[SDCC_NAME_MAX + 1];
5034 /* if the switch statement does not exist */
5035 /* then case is out of context */
5038 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5042 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5043 /* if not a constant then error */
5044 if (!IS_LITERAL (caseVal->ftype))
5046 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5050 /* if not a integer than error */
5051 if (!IS_INTEGRAL (caseVal->ftype))
5053 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5057 /* find the end of the switch values chain */
5058 if (!(val = swStat->values.switchVals.swVals))
5059 swStat->values.switchVals.swVals = caseVal->opval.val;
5062 /* also order the cases according to value */
5064 int cVal = (int) ulFromVal (caseVal->opval.val);
5065 while (val && (int) ulFromVal (val) < cVal)
5071 /* if we reached the end then */
5074 pval->next = caseVal->opval.val;
5076 else if ((int) ulFromVal (val) == cVal)
5078 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5084 /* we found a value greater than */
5085 /* the current value we must add this */
5086 /* before the value */
5087 caseVal->opval.val->next = val;
5089 /* if this was the first in chain */
5090 if (swStat->values.switchVals.swVals == val)
5091 swStat->values.switchVals.swVals =
5094 pval->next = caseVal->opval.val;
5099 /* create the case label */
5100 SNPRINTF(caseLbl, sizeof(caseLbl),
5102 swStat->values.switchVals.swNum,
5103 (int) ulFromVal (caseVal->opval.val));
5105 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5106 rexpr->filename = 0;
5111 /*-----------------------------------------------------------------*/
5112 /* createDefault - creates the parse tree for the default statement */
5113 /*-----------------------------------------------------------------*/
5115 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5117 char defLbl[SDCC_NAME_MAX + 1];
5119 /* if the switch statement does not exist */
5120 /* then case is out of context */
5123 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5127 if (swStat->values.switchVals.swDefault)
5129 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5134 /* turn on the default flag */
5135 swStat->values.switchVals.swDefault = 1;
5137 /* create the label */
5138 SNPRINTF (defLbl, sizeof(defLbl),
5139 "_default_%d", swStat->values.switchVals.swNum);
5140 return createLabel (newSymbol (defLbl, 0), stmnt);
5143 /*-----------------------------------------------------------------*/
5144 /* createIf - creates the parsetree for the if statement */
5145 /*-----------------------------------------------------------------*/
5147 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5149 static int Lblnum = 0;
5151 symbol *ifTrue, *ifFalse, *ifEnd;
5153 /* if neither exists */
5154 if (!elseBody && !ifBody) {
5155 // if there are no side effects (i++, j() etc)
5156 if (!hasSEFcalls(condAst)) {
5161 /* create the labels */
5162 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5163 ifFalse = newSymbol (buffer, NestLevel);
5164 /* if no else body then end == false */
5169 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5170 ifEnd = newSymbol (buffer, NestLevel);
5173 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5174 ifTrue = newSymbol (buffer, NestLevel);
5178 /* attach the ifTrue label to the top of it body */
5179 ifBody = createLabel (ifTrue, ifBody);
5180 /* attach a goto end to the ifBody if else is present */
5183 ifBody = newNode (NULLOP, ifBody,
5185 newAst_VALUE (symbolVal (ifEnd)),
5187 /* put the elseLabel on the else body */
5188 elseBody = createLabel (ifFalse, elseBody);
5189 /* out the end at the end of the body */
5190 elseBody = newNode (NULLOP,
5192 createLabel (ifEnd, NULL));
5196 ifBody = newNode (NULLOP, ifBody,
5197 createLabel (ifFalse, NULL));
5199 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5200 if (IS_IFX (condAst))
5203 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5205 return newNode (NULLOP, ifTree,
5206 newNode (NULLOP, ifBody, elseBody));
5210 /*-----------------------------------------------------------------*/
5211 /* createDo - creates parse tree for do */
5214 /* _docontinue_n: */
5215 /* condition_expression +-> trueLabel -> _dobody_n */
5217 /* +-> falseLabel-> _dobreak_n */
5219 /*-----------------------------------------------------------------*/
5221 createDo (symbol * trueLabel, symbol * continueLabel,
5222 symbol * falseLabel, ast * condAst, ast * doBody)
5227 /* if the body does not exist then it is simple */
5230 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5231 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5232 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5233 doTree->trueLabel = continueLabel;
5234 doTree->falseLabel = NULL;
5236 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5240 /* otherwise we have a body */
5241 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5243 /* attach the body label to the top */
5244 doBody = createLabel (trueLabel, doBody);
5245 /* attach the continue label to end of body */
5246 doBody = newNode (NULLOP, doBody,
5247 createLabel (continueLabel, NULL));
5249 /* now put the break label at the end */
5250 if (IS_IFX (condAst))
5253 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5255 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5257 /* putting it together */
5258 return newNode (NULLOP, doBody, doTree);
5261 /*-----------------------------------------------------------------*/
5262 /* createFor - creates parse tree for 'for' statement */
5265 /* condExpr +-> trueLabel -> _forbody_n */
5267 /* +-> falseLabel-> _forbreak_n */
5270 /* _forcontinue_n: */
5272 /* goto _forcond_n ; */
5274 /*-----------------------------------------------------------------*/
5276 createFor (symbol * trueLabel, symbol * continueLabel,
5277 symbol * falseLabel, symbol * condLabel,
5278 ast * initExpr, ast * condExpr, ast * loopExpr,
5283 /* if loopexpression not present then we can generate it */
5284 /* the same way as a while */
5286 return newNode (NULLOP, initExpr,
5287 createWhile (trueLabel, continueLabel,
5288 falseLabel, condExpr, forBody));
5289 /* vanilla for statement */
5290 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5292 if (condExpr && !IS_IFX (condExpr))
5293 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5296 /* attach condition label to condition */
5297 condExpr = createLabel (condLabel, condExpr);
5299 /* attach body label to body */
5300 forBody = createLabel (trueLabel, forBody);
5302 /* attach continue to forLoop expression & attach */
5303 /* goto the forcond @ and of loopExpression */
5304 loopExpr = createLabel (continueLabel,
5308 newAst_VALUE (symbolVal (condLabel)),
5310 /* now start putting them together */
5311 forTree = newNode (NULLOP, initExpr, condExpr);
5312 forTree = newNode (NULLOP, forTree, forBody);
5313 forTree = newNode (NULLOP, forTree, loopExpr);
5314 /* finally add the break label */
5315 forTree = newNode (NULLOP, forTree,
5316 createLabel (falseLabel, NULL));
5320 /*-----------------------------------------------------------------*/
5321 /* createWhile - creates parse tree for while statement */
5322 /* the while statement will be created as follows */
5324 /* _while_continue_n: */
5325 /* condition_expression +-> trueLabel -> _while_boby_n */
5327 /* +-> falseLabel -> _while_break_n */
5328 /* _while_body_n: */
5330 /* goto _while_continue_n */
5331 /* _while_break_n: */
5332 /*-----------------------------------------------------------------*/
5334 createWhile (symbol * trueLabel, symbol * continueLabel,
5335 symbol * falseLabel, ast * condExpr, ast * whileBody)
5339 /* put the continue label */
5340 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5341 condExpr = createLabel (continueLabel, condExpr);
5342 condExpr->filename = NULL;
5343 condExpr->lineno = 0;
5345 /* put the body label in front of the body */
5346 whileBody = createLabel (trueLabel, whileBody);
5347 whileBody->filename = NULL;
5348 whileBody->lineno = 0;
5349 /* put a jump to continue at the end of the body */
5350 /* and put break label at the end of the body */
5351 whileBody = newNode (NULLOP,
5354 newAst_VALUE (symbolVal (continueLabel)),
5355 createLabel (falseLabel, NULL)));
5357 /* put it all together */
5358 if (IS_IFX (condExpr))
5359 whileTree = condExpr;
5362 whileTree = newNode (IFX, condExpr, NULL);
5363 /* put the true & false labels in place */
5364 whileTree->trueLabel = trueLabel;
5365 whileTree->falseLabel = falseLabel;
5368 return newNode (NULLOP, whileTree, whileBody);
5371 /*-----------------------------------------------------------------*/
5372 /* isShiftRightLitVal _BitAndLitVal - helper function */
5373 /*-----------------------------------------------------------------*/
5375 isShiftRightLitVal_BitAndLitVal (ast * tree)
5377 /* if this is not a bit and */
5378 if (!IS_BITAND (tree))
5381 /* will look for tree of the form
5382 ( expr >> litval2) & litval1 */
5383 if (!IS_AST_LIT_VALUE (tree->right))
5386 if (!IS_RIGHT_OP (tree->left))
5389 if (!IS_AST_LIT_VALUE (tree->left->right))
5392 return tree->left->left;
5395 /*-----------------------------------------------------------------*/
5396 /* isBitAndPowOf2 - helper function */
5397 /*-----------------------------------------------------------------*/
5399 isBitAndPow2 (ast * tree)
5401 /* if this is not a bit and */
5402 if (!IS_BITAND (tree))
5405 /* will look for tree of the form
5406 ( expr & (1 << litval) */
5407 if (!IS_AST_LIT_VALUE (tree->right))
5410 return powof2 (AST_ULONG_VALUE (tree->right));
5413 /*-----------------------------------------------------------------*/
5414 /* optimizeGetHbit - get highest order bit of the expression */
5415 /*-----------------------------------------------------------------*/
5417 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5422 expr = isShiftRightLitVal_BitAndLitVal(tree);
5425 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5426 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5427 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5430 if (!expr && (resultType == RESULT_TYPE_BIT))
5433 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5439 /* make sure the port supports GETHBIT */
5440 if (port->hasExtBitOp
5441 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5444 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5447 /*-----------------------------------------------------------------*/
5448 /* optimizeGetAbit - get a single bit of the expression */
5449 /*-----------------------------------------------------------------*/
5451 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5456 expr = isShiftRightLitVal_BitAndLitVal(tree);
5459 if (AST_ULONG_VALUE (tree->right) != 1)
5461 count = tree->left->right;
5463 if (!expr && (resultType == RESULT_TYPE_BIT))
5465 int p2 = isBitAndPow2 (tree);
5469 count = newAst_VALUE (valueFromLit (p2));
5475 /* make sure the port supports GETABIT */
5476 if (port->hasExtBitOp
5477 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5480 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5484 /*-----------------------------------------------------------------*/
5485 /* optimizeGetByte - get a byte of the expression */
5486 /*-----------------------------------------------------------------*/
5488 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5494 expr = isShiftRightLitVal_BitAndLitVal(tree);
5497 i = AST_ULONG_VALUE (tree->left->right);
5498 count = tree->left->right;
5499 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5502 if (!expr && resultType == RESULT_TYPE_CHAR)
5504 /* if this is a right shift over a multiple of 8 */
5505 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5507 i = AST_ULONG_VALUE (tree->right);
5508 count = tree->right;
5512 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5515 /* make sure the port supports GETBYTE */
5516 if (port->hasExtBitOp
5517 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5520 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5523 /*-----------------------------------------------------------------*/
5524 /* optimizeGetWord - get two bytes of the expression */
5525 /*-----------------------------------------------------------------*/
5527 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5533 expr = isShiftRightLitVal_BitAndLitVal(tree);
5536 i = AST_ULONG_VALUE (tree->left->right);
5537 count = tree->left->right;
5538 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5541 if (!expr && resultType == RESULT_TYPE_INT)
5543 /* if this is a right shift over a multiple of 8 */
5544 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5546 i = AST_ULONG_VALUE (tree->right);
5547 count = tree->right;
5551 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5554 /* make sure the port supports GETWORD */
5555 if (port->hasExtBitOp
5556 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5559 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5562 /*-----------------------------------------------------------------*/
5563 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5564 /*-----------------------------------------------------------------*/
5566 optimizeRRCRLC (ast * root)
5568 /* will look for trees of the form
5569 (?expr << 1) | (?expr >> 7) or
5570 (?expr >> 7) | (?expr << 1) will make that
5571 into a RLC : operation ..
5573 (?expr >> 1) | (?expr << 7) or
5574 (?expr << 7) | (?expr >> 1) will make that
5575 into a RRC operation
5576 note : by 7 I mean (number of bits required to hold the
5578 /* if the root operation is not a | operation then not */
5579 if (!IS_BITOR (root))
5582 /* I have to think of a better way to match patterns this sucks */
5583 /* that aside let's start looking for the first case : I use a
5584 negative check a lot to improve the efficiency */
5585 /* (?expr << 1) | (?expr >> 7) */
5586 if (IS_LEFT_OP (root->left) &&
5587 IS_RIGHT_OP (root->right))
5590 if (!SPEC_USIGN (TETYPE (root->left->left)))
5593 if (!IS_AST_LIT_VALUE (root->left->right) ||
5594 !IS_AST_LIT_VALUE (root->right->right))
5597 /* make sure it is the same expression */
5598 if (!isAstEqual (root->left->left,
5602 if (AST_ULONG_VALUE (root->left->right) != 1)
5605 if (AST_ULONG_VALUE (root->right->right) !=
5606 (getSize (TTYPE (root->left->left)) * 8 - 1))
5609 /* make sure the port supports RLC */
5610 if (port->hasExtBitOp
5611 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5614 /* whew got the first case : create the AST */
5615 return newNode (RLC, root->left->left, NULL);
5619 /* check for second case */
5620 /* (?expr >> 7) | (?expr << 1) */
5621 if (IS_LEFT_OP (root->right) &&
5622 IS_RIGHT_OP (root->left))
5625 if (!SPEC_USIGN (TETYPE (root->left->left)))
5628 if (!IS_AST_LIT_VALUE (root->left->right) ||
5629 !IS_AST_LIT_VALUE (root->right->right))
5632 /* make sure it is the same symbol */
5633 if (!isAstEqual (root->left->left,
5637 if (AST_ULONG_VALUE (root->right->right) != 1)
5640 if (AST_ULONG_VALUE (root->left->right) !=
5641 (getSize (TTYPE (root->left->left)) * 8 - 1))
5644 /* make sure the port supports RLC */
5645 if (port->hasExtBitOp
5646 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5649 /* whew got the first case : create the AST */
5650 return newNode (RLC, root->left->left, NULL);
5655 /* third case for RRC */
5656 /* (?symbol >> 1) | (?symbol << 7) */
5657 if (IS_LEFT_OP (root->right) &&
5658 IS_RIGHT_OP (root->left))
5661 if (!SPEC_USIGN (TETYPE (root->left->left)))
5664 if (!IS_AST_LIT_VALUE (root->left->right) ||
5665 !IS_AST_LIT_VALUE (root->right->right))
5668 /* make sure it is the same symbol */
5669 if (!isAstEqual (root->left->left,
5673 if (AST_ULONG_VALUE (root->left->right) != 1)
5676 if (AST_ULONG_VALUE (root->right->right) !=
5677 (getSize (TTYPE (root->left->left)) * 8 - 1))
5680 /* make sure the port supports RRC */
5681 if (port->hasExtBitOp
5682 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5685 /* whew got the first case : create the AST */
5686 return newNode (RRC, root->left->left, NULL);
5690 /* fourth and last case for now */
5691 /* (?symbol << 7) | (?symbol >> 1) */
5692 if (IS_RIGHT_OP (root->right) &&
5693 IS_LEFT_OP (root->left))
5696 if (!SPEC_USIGN (TETYPE (root->left->left)))
5699 if (!IS_AST_LIT_VALUE (root->left->right) ||
5700 !IS_AST_LIT_VALUE (root->right->right))
5703 /* make sure it is the same symbol */
5704 if (!isAstEqual (root->left->left,
5708 if (AST_ULONG_VALUE (root->right->right) != 1)
5711 if (AST_ULONG_VALUE (root->left->right) !=
5712 (getSize (TTYPE (root->left->left)) * 8 - 1))
5715 /* make sure the port supports RRC */
5716 if (port->hasExtBitOp
5717 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5720 /* whew got the first case : create the AST */
5721 return newNode (RRC, root->left->left, NULL);
5725 /* not found return root */
5729 /*-----------------------------------------------------------------*/
5730 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5731 /*-----------------------------------------------------------------*/
5733 optimizeSWAP (ast * root)
5735 /* will look for trees of the form
5736 (?expr << 4) | (?expr >> 4) or
5737 (?expr >> 4) | (?expr << 4) will make that
5738 into a SWAP : operation ..
5739 note : by 4 I mean (number of bits required to hold the
5741 /* if the root operation is not a | operation then not */
5742 if (!IS_BITOR (root))
5745 /* (?expr << 4) | (?expr >> 4) */
5746 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5747 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5750 if (!SPEC_USIGN (TETYPE (root->left->left)))
5753 if (!IS_AST_LIT_VALUE (root->left->right) ||
5754 !IS_AST_LIT_VALUE (root->right->right))
5757 /* make sure it is the same expression */
5758 if (!isAstEqual (root->left->left,
5762 if (AST_ULONG_VALUE (root->left->right) !=
5763 (getSize (TTYPE (root->left->left)) * 4))
5766 if (AST_ULONG_VALUE (root->right->right) !=
5767 (getSize (TTYPE (root->left->left)) * 4))
5770 /* make sure the port supports SWAP */
5771 if (port->hasExtBitOp
5772 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5775 /* found it : create the AST */
5776 return newNode (SWAP, root->left->left, NULL);
5780 /* not found return root */
5784 /*-----------------------------------------------------------------*/
5785 /* optimizeCompare - optimizes compares for bit variables */
5786 /*-----------------------------------------------------------------*/
5788 optimizeCompare (ast * root)
5790 ast *optExpr = NULL;
5793 unsigned int litValue;
5795 /* if nothing then return nothing */
5799 /* if not a compare op then do leaves */
5800 if (!IS_COMPARE_OP (root))
5802 root->left = optimizeCompare (root->left);
5803 root->right = optimizeCompare (root->right);
5807 /* if left & right are the same then depending
5808 of the operation do */
5809 if (isAstEqual (root->left, root->right))
5811 switch (root->opval.op)
5816 optExpr = newAst_VALUE (constCharVal (0));
5821 optExpr = newAst_VALUE (constCharVal (1));
5825 return decorateType (optExpr, RESULT_TYPE_NONE);
5828 vleft = (root->left->type == EX_VALUE ?
5829 root->left->opval.val : NULL);
5831 vright = (root->right->type == EX_VALUE ?
5832 root->right->opval.val : NULL);
5834 /* if left is a BITVAR in BITSPACE */
5835 /* and right is a LITERAL then */
5836 /* optimize else do nothing */
5837 if (vleft && vright &&
5838 IS_BITVAR (vleft->etype) &&
5839 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5840 IS_LITERAL (vright->etype))
5843 /* if right side > 1 then comparison may never succeed */
5844 if ((litValue = (int) ulFromVal (vright)) > 1)
5846 werror (W_BAD_COMPARE);
5852 switch (root->opval.op)
5854 case '>': /* bit value greater than 1 cannot be */
5855 werror (W_BAD_COMPARE);
5859 case '<': /* bit value < 1 means 0 */
5861 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5864 case LE_OP: /* bit value <= 1 means no check */
5865 optExpr = newAst_VALUE (vright);
5868 case GE_OP: /* bit value >= 1 means only check for = */
5870 optExpr = newAst_VALUE (vleft);
5875 { /* literal is zero */
5876 switch (root->opval.op)
5878 case '<': /* bit value < 0 cannot be */
5879 werror (W_BAD_COMPARE);
5883 case '>': /* bit value > 0 means 1 */
5885 optExpr = newAst_VALUE (vleft);
5888 case LE_OP: /* bit value <= 0 means no check */
5889 case GE_OP: /* bit value >= 0 means no check */
5890 werror (W_BAD_COMPARE);
5894 case EQ_OP: /* bit == 0 means ! of bit */
5895 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5899 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5900 } /* end-of-if of BITVAR */
5906 /*-----------------------------------------------------------------*/
5907 /* addSymToBlock : adds the symbol to the first block we find */
5908 /*-----------------------------------------------------------------*/
5910 addSymToBlock (symbol * sym, ast * tree)
5912 /* reached end of tree or a leaf */
5913 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5917 if (IS_AST_OP (tree) &&
5918 tree->opval.op == BLOCK)
5921 symbol *lsym = copySymbol (sym);
5923 lsym->next = AST_VALUES (tree, sym);
5924 AST_VALUES (tree, sym) = lsym;
5928 addSymToBlock (sym, tree->left);
5929 addSymToBlock (sym, tree->right);
5932 /*-----------------------------------------------------------------*/
5933 /* processRegParms - do processing for register parameters */
5934 /*-----------------------------------------------------------------*/
5936 processRegParms (value * args, ast * body)
5940 if (IS_REGPARM (args->etype))
5941 addSymToBlock (args->sym, body);
5946 /*-----------------------------------------------------------------*/
5947 /* resetParmKey - resets the operandkeys for the symbols */
5948 /*-----------------------------------------------------------------*/
5949 DEFSETFUNC (resetParmKey)
5962 /*------------------------------------------------------------------*/
5963 /* fixupInlineLabel - change a label in an inlined function so that */
5964 /* it is always unique no matter how many times */
5965 /* the function is inlined. */
5966 /*------------------------------------------------------------------*/
5968 fixupInlineLabel (symbol * sym)
5970 char name[SDCC_NAME_MAX + 1];
5972 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5973 strcpy (sym->name, name);
5977 /*------------------------------------------------------------------*/
5978 /* copyAstLoc - copy location information (file, line, block, etc.) */
5979 /* from one ast node to another */
5980 /*------------------------------------------------------------------*/
5982 copyAstLoc (ast * dest, ast * src)
5984 dest->filename = src->filename;
5985 dest->lineno = src->lineno;
5986 dest->level = src->level;
5987 dest->block = src->block;
5988 dest->seqPoint = src->seqPoint;
5993 /*-----------------------------------------------------------------*/
5994 /* fixupInline - perform various fixups on an inline function tree */
5995 /* to take into account that it is no longer a */
5996 /* stand-alone function. */
5997 /*-----------------------------------------------------------------*/
5999 fixupInline (ast * tree, int level)
6001 tree->block = currBlockno;
6003 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6010 /* Add any declared variables back into the symbol table */
6011 decls = tree->values.sym;
6014 decls->level = level;
6015 decls->block = currBlockno;
6016 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6017 decls = decls->next;
6021 tree->level = level;
6023 /* Update symbols */
6024 if (IS_AST_VALUE (tree) &&
6025 tree->opval.val->sym)
6027 symbol * sym = tree->opval.val->sym;
6030 sym->block = currBlockno;
6033 SYM_SPIL_LOC (sym) = NULL;
6036 /* If the symbol is a label, we need to renumber it */
6038 fixupInlineLabel (sym);
6041 /* Update IFX target labels */
6042 if (tree->type == EX_OP && tree->opval.op == IFX)
6044 if (tree->trueLabel)
6045 fixupInlineLabel (tree->trueLabel);
6046 if (tree->falseLabel)
6047 fixupInlineLabel (tree->falseLabel);
6050 /* Replace RETURN with optional assignment and a GOTO to the end */
6051 /* of the inlined function */
6052 if (tree->type == EX_OP && tree->opval.op == RETURN)
6054 ast * assignTree = NULL;
6057 if (inlineState.retsym && tree->right)
6059 assignTree = newNode ('=',
6060 newAst_VALUE (symbolVal (inlineState.retsym)),
6062 copyAstLoc (assignTree, tree);
6065 gotoTree = newNode (GOTO,
6066 newAst_VALUE (symbolVal (inlineState.retlab)),
6068 copyAstLoc (gotoTree, tree);
6070 tree->opval.op = NULLOP;
6071 tree->left = assignTree;
6072 tree->right = gotoTree;
6075 /* Update any children */
6077 fixupInline (tree->left, level);
6079 fixupInline (tree->right, level);
6081 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6083 symbol * label = tree->left->opval.val->sym;
6085 label->key = labelKey++;
6086 /* Add this label back into the symbol table */
6087 addSym (LabelTab, label, label->name, label->level, 0, 0);
6091 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6097 /*-----------------------------------------------------------------*/
6098 /* inlineAddDecl - add a variable declaration to an ast block. It */
6099 /* is also added to the symbol table if addSymTab */
6101 /*-----------------------------------------------------------------*/
6103 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6106 SYM_SPIL_LOC (sym) = NULL;
6110 symbol **decl = &(block->values.sym);
6112 sym->level = block->level;
6113 sym->block = block->block;
6117 if (strcmp ((*decl)->name, sym->name) == 0)
6119 decl = &( (*decl)->next );
6125 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6131 /*-----------------------------------------------------------------*/
6132 /* inlineTempVar - create a temporary variable for inlining */
6133 /*-----------------------------------------------------------------*/
6135 inlineTempVar (sym_link * type, int level)
6139 sym = newSymbol (genSymName(level), level );
6140 sym->type = copyLinkChain (type);
6141 sym->etype = getSpec(sym->type);
6142 SPEC_SCLS (sym->etype) = S_AUTO;
6143 SPEC_OCLS (sym->etype) = NULL;
6144 SPEC_EXTR (sym->etype) = 0;
6145 SPEC_STAT (sym->etype) = 0;
6146 if IS_SPEC (sym->type)
6147 SPEC_VOLATILE (sym->type) = 0;
6149 DCL_PTR_VOLATILE (sym->type) = 0;
6150 SPEC_ABSA (sym->etype) = 0;
6156 /*-----------------------------------------------------------------*/
6157 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6158 /*-----------------------------------------------------------------*/
6160 inlineFindParmRecurse (ast * parms, int *index)
6165 if (parms->type == EX_OP && parms->opval.op == PARAM)
6169 p=inlineFindParmRecurse (parms->left, index);
6172 p=inlineFindParmRecurse (parms->right, index);
6183 /*-----------------------------------------------------------------*/
6184 /* inlineFindParm - search an ast tree of parameters to find one */
6185 /* at a particular index (0=first parameter). */
6186 /* Returns NULL if not found. */
6187 /*-----------------------------------------------------------------*/
6189 inlineFindParm (ast * parms, int index)
6191 return inlineFindParmRecurse (parms, &index);
6194 /*-----------------------------------------------------------------*/
6195 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6196 /*-----------------------------------------------------------------*/
6198 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6205 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6206 if (tempBlockno > maxBlockno)
6207 maxBlockno = tempBlockno;
6209 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6210 if (tempBlockno > maxBlockno)
6211 maxBlockno = tempBlockno;
6213 if (tree->block > maxBlockno)
6214 maxBlockno = tree->block;
6221 /*-----------------------------------------------------------------*/
6222 /* expandInlineFuncs - replace calls to inline functions with the */
6223 /* function itself */
6224 /*-----------------------------------------------------------------*/
6226 expandInlineFuncs (ast * tree, ast * block)
6228 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6229 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6231 symbol * func = tree->left->opval.val->sym;
6234 /* The symbol is probably not bound yet, so find the real one */
6235 csym = findSymWithLevel (SymbolTab, func);
6239 /* Is this an inline function that we can inline? */
6240 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6242 symbol * retsym = NULL;
6250 /* Generate a label for the inlined function to branch to */
6251 /* in case it contains a return statement */
6252 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6255 inlineState.retlab = retlab;
6257 /* Build the subtree for the inlined function in the form: */
6258 /* { //inlinetree block */
6259 /* { //inlinetree2 block */
6260 /* inline_function_code; */
6264 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6265 copyAstLoc (temptree, tree);
6266 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6267 copyAstLoc (temptree, tree);
6268 temptree = newNode (BLOCK, NULL, temptree);
6269 copyAstLoc (temptree, tree);
6270 inlinetree2 = temptree;
6271 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6272 copyAstLoc (inlinetree, tree);
6274 /* To pass parameters to the inlined function, we need some */
6275 /* intermediate variables. This avoids scoping problems */
6276 /* when the parameter declaration names are used differently */
6277 /* during the function call. For example, a function */
6278 /* declared as func(int x, int y) but called as func(y,x). */
6279 /* { //inlinetree block */
6280 /* type1 temparg1; */
6282 /* typen tempargn; */
6283 /* temparg1 = argument1; */
6285 /* tempargn = argumentn; */
6286 /* { //inlinetree2 block */
6290 /* param1 = temparg1; */
6292 /* paramn = tempargn; */
6293 /* inline_function_code; */
6297 args = FUNC_ARGS (func->type);
6304 symbol * parm = copySymbol (args->sym);
6306 temparg = inlineTempVar (args->sym->type, tree->level+1);
6307 inlineAddDecl (temparg, inlinetree, FALSE);
6309 passedarg = inlineFindParm (tree->right, argIndex);
6310 assigntree = newNode ('=',
6311 newAst_VALUE (symbolVal (temparg)),
6313 inlinetree->right = newNode (NULLOP,
6317 inlineAddDecl (parm, inlinetree2, FALSE);
6320 assigntree = newNode ('=',
6321 newAst_VALUE (symbolVal (parm)),
6322 newAst_VALUE (symbolVal (temparg)));
6323 inlinetree2->right = newNode (NULLOP,
6325 inlinetree2->right);
6332 /* Handle the return type */
6333 if (!IS_VOID (func->type->next))
6335 /* Create a temporary symbol to hold the return value and */
6336 /* join it with the inlined function using the comma */
6337 /* operator. The fixupInline function will take care of */
6338 /* changing return statements into assignments to retsym. */
6339 /* (parameter passing and return label omitted for clarity) */
6340 /* rettype retsym; */
6342 /* {{inline_function_code}}, retsym */
6344 retsym = inlineTempVar (func->type->next, tree->level);
6345 inlineAddDecl (retsym, block, TRUE);
6347 tree->opval.op = ',';
6348 tree->left = inlinetree;
6349 tree->right = newAst_VALUE (symbolVal (retsym));
6353 tree->opval.op = NULLOP;
6355 tree->right = inlinetree;
6357 inlineState.retsym = retsym;
6359 /* Renumber the various internal counters on the inlined */
6360 /* function's tree nodes and symbols. Add the inlined */
6361 /* function's local variables to the appropriate scope(s). */
6362 /* Convert inlined return statements to an assignment to */
6363 /* retsym (if needed) and a goto retlab. */
6364 fixupInline (inlinetree, inlinetree->level);
6365 inlineState.count++;
6370 /* Recursively continue to search for functions to inline. */
6371 if (IS_AST_OP (tree))
6373 if (tree->opval.op == BLOCK)
6377 expandInlineFuncs (tree->left, block);
6379 expandInlineFuncs (tree->right, block);
6384 /*-----------------------------------------------------------------*/
6385 /* createFunction - This is the key node that calls the iCode for */
6386 /* generating the code for a function. Note code */
6387 /* is generated function by function, later when */
6388 /* add inter-procedural analysis this will change */
6389 /*-----------------------------------------------------------------*/
6391 createFunction (symbol * name, ast * body)
6397 iCode *piCode = NULL;
6400 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6401 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6403 /* if check function return 0 then some problem */
6404 if (checkFunction (name, NULL) == 0)
6407 /* create a dummy block if none exists */
6409 body = newNode (BLOCK, NULL, NULL);
6413 /* check if the function name already in the symbol table */
6414 if ((csym = findSym (SymbolTab, NULL, name->name)))
6417 /* special case for compiler defined functions
6418 we need to add the name to the publics list : this
6419 actually means we are now compiling the compiler
6423 addSet (&publics, name);
6428 addSymChain (&name);
6429 allocVariables (name);
6431 name->lastLine = lexLineno;
6434 /* set the stack pointer */
6435 stackPtr = -port->stack.direction * port->stack.call_overhead;
6438 if (IFFUNC_ISISR (name->type))
6439 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6441 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6443 if (options.useXstack)
6444 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6446 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6449 fetype = getSpec (name->type); /* get the specifier for the function */
6450 /* if this is a reentrant function then */
6451 if (IFFUNC_ISREENT (name->type))
6454 inlineState.count = 0;
6455 savedBlockno = currBlockno;
6456 currBlockno = inlineFindMaxBlockno (body, 0);
6457 expandInlineFuncs (body, NULL);
6458 currBlockno = savedBlockno;
6460 if (FUNC_ISINLINE (name->type))
6461 name->funcTree = copyAst (body);
6463 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6465 /* do processing for parameters that are passed in registers */
6466 processRegParms (FUNC_ARGS(name->type), body);
6468 /* set the stack pointer */
6472 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6474 /* allocate & autoinit the block variables */
6475 processBlockVars (body, &stack, ALLOCATE);
6477 /* name needs to be mangled */
6478 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6480 body = resolveSymbols (body); /* resolve the symbols */
6481 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6483 /* save the stack information */
6484 if (options.useXstack)
6485 name->xstack = SPEC_STAK (fetype) = stack;
6487 name->stack = SPEC_STAK (fetype) = stack;
6489 ex = newAst_VALUE (symbolVal (name)); /* create name */
6490 ex = newNode (FUNCTION, ex, body);
6491 ex->values.args = FUNC_ARGS(name->type);
6493 if (options.dump_tree)
6498 /* Do not generate code for inline functions unless extern also. */
6500 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6503 /* Temporary hack: always generate code for static inline functions. */
6504 /* Ideally static inline functions should only be generated if needed. */
6505 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6509 /* create the node & generate intermediate code */
6511 codeOutBuf = &code->oBuf;
6512 piCode = iCodeFromAst (ex);
6513 name->generated = 1;
6518 eBBlockFromiCode (piCode);
6520 /* if there are any statics then do them */
6523 GcurMemmap = statsg;
6524 codeOutBuf = &statsg->oBuf;
6525 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6531 /* dealloc the block variables */
6532 processBlockVars (body, &stack, DEALLOCATE);
6533 outputDebugStackSymbols();
6534 /* deallocate paramaters */
6535 deallocParms (FUNC_ARGS(name->type));
6537 if (IFFUNC_ISREENT (name->type))
6540 /* we are done freeup memory & cleanup */
6542 if (port->reset_labelKey) labelKey = 1;
6544 FUNC_HASBODY(name->type) = 1;
6545 addSet (&operKeyReset, name);
6546 applyToSet (operKeyReset, resetParmKey);
6551 cleanUpLevel (LabelTab, 0);
6552 cleanUpBlock (StructTab, 1);
6553 cleanUpBlock (TypedefTab, 1);
6555 xstack->syms = NULL;
6556 istack->syms = NULL;
6561 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6562 /*-----------------------------------------------------------------*/
6563 /* ast_print : prints the ast (for debugging purposes) */
6564 /*-----------------------------------------------------------------*/
6566 void ast_print (ast * tree, FILE *outfile, int indent)
6571 /* can print only decorated trees */
6572 if (!tree->decorated) return;
6574 /* if any child is an error | this one is an error do nothing */
6575 if (tree->isError ||
6576 (tree->left && tree->left->isError) ||
6577 (tree->right && tree->right->isError)) {
6578 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6582 /* print the line */
6583 /* if not block & function */
6584 if (tree->type == EX_OP &&
6585 (tree->opval.op != FUNCTION &&
6586 tree->opval.op != BLOCK &&
6587 tree->opval.op != NULLOP)) {
6590 if (tree->opval.op == FUNCTION) {
6592 value *args=FUNC_ARGS(tree->left->opval.val->type);
6593 fprintf(outfile,"FUNCTION (%s=%p) type (",
6594 tree->left->opval.val->name, tree);
6595 printTypeChain (tree->left->opval.val->type->next,outfile);
6596 fprintf(outfile,") args (");
6599 fprintf (outfile, ", ");
6601 printTypeChain (args ? args->type : NULL, outfile);
6603 args= args ? args->next : NULL;
6605 fprintf(outfile,")\n");
6606 ast_print(tree->left,outfile,indent);
6607 ast_print(tree->right,outfile,indent);
6610 if (tree->opval.op == BLOCK) {
6611 symbol *decls = tree->values.sym;
6612 INDENT(indent,outfile);
6613 fprintf(outfile,"{\n");
6615 INDENT(indent+2,outfile);
6616 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6617 decls->name, decls);
6618 printTypeChain(decls->type,outfile);
6619 fprintf(outfile,")\n");
6621 decls = decls->next;
6623 ast_print(tree->right,outfile,indent+2);
6624 INDENT(indent,outfile);
6625 fprintf(outfile,"}\n");
6628 if (tree->opval.op == NULLOP) {
6629 ast_print(tree->left,outfile,indent);
6630 ast_print(tree->right,outfile,indent);
6633 INDENT(indent,outfile);
6635 /*------------------------------------------------------------------*/
6636 /*----------------------------*/
6637 /* leaf has been reached */
6638 /*----------------------------*/
6639 /* if this is of type value */
6640 /* just get the type */
6641 if (tree->type == EX_VALUE) {
6643 if (IS_LITERAL (tree->opval.val->etype)) {
6644 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6645 if (SPEC_USIGN (tree->opval.val->etype))
6646 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6648 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6649 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6650 floatFromVal(tree->opval.val));
6651 } else if (tree->opval.val->sym) {
6652 /* if the undefined flag is set then give error message */
6653 if (tree->opval.val->sym->undefined) {
6654 fprintf(outfile,"UNDEFINED SYMBOL ");
6656 fprintf(outfile,"SYMBOL ");
6658 fprintf(outfile,"(%s=%p @ %p)",
6659 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6662 fprintf(outfile," type (");
6663 printTypeChain(tree->ftype,outfile);
6664 fprintf(outfile,")\n");
6666 fprintf(outfile,"\n");
6671 /* if type link for the case of cast */
6672 if (tree->type == EX_LINK) {
6673 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6674 printTypeChain(tree->opval.lnk,outfile);
6675 fprintf(outfile,")\n");
6680 /* depending on type of operator do */
6682 switch (tree->opval.op) {
6683 /*------------------------------------------------------------------*/
6684 /*----------------------------*/
6686 /*----------------------------*/
6688 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6689 printTypeChain(tree->ftype,outfile);
6690 fprintf(outfile,")\n");
6691 ast_print(tree->left,outfile,indent+2);
6692 ast_print(tree->right,outfile,indent+2);
6695 /*------------------------------------------------------------------*/
6696 /*----------------------------*/
6698 /*----------------------------*/
6700 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6701 printTypeChain(tree->ftype,outfile);
6702 fprintf(outfile,")\n");
6703 ast_print(tree->left,outfile,indent+2);
6704 ast_print(tree->right,outfile,indent+2);
6707 /*------------------------------------------------------------------*/
6708 /*----------------------------*/
6709 /* struct/union pointer */
6710 /*----------------------------*/
6712 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6713 printTypeChain(tree->ftype,outfile);
6714 fprintf(outfile,")\n");
6715 ast_print(tree->left,outfile,indent+2);
6716 ast_print(tree->right,outfile,indent+2);
6719 /*------------------------------------------------------------------*/
6720 /*----------------------------*/
6721 /* ++/-- operation */
6722 /*----------------------------*/
6725 fprintf(outfile,"post-");
6727 fprintf(outfile,"pre-");
6728 fprintf(outfile,"INC_OP (%p) type (",tree);
6729 printTypeChain(tree->ftype,outfile);
6730 fprintf(outfile,")\n");
6731 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6732 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6737 fprintf(outfile,"post-");
6739 fprintf(outfile,"pre-");
6740 fprintf(outfile,"DEC_OP (%p) type (",tree);
6741 printTypeChain(tree->ftype,outfile);
6742 fprintf(outfile,")\n");
6743 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6744 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6747 /*------------------------------------------------------------------*/
6748 /*----------------------------*/
6750 /*----------------------------*/
6753 fprintf(outfile,"& (%p) type (",tree);
6754 printTypeChain(tree->ftype,outfile);
6755 fprintf(outfile,")\n");
6756 ast_print(tree->left,outfile,indent+2);
6757 ast_print(tree->right,outfile,indent+2);
6759 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6760 printTypeChain(tree->ftype,outfile);
6761 fprintf(outfile,")\n");
6762 ast_print(tree->left,outfile,indent+2);
6763 ast_print(tree->right,outfile,indent+2);
6766 /*----------------------------*/
6768 /*----------------------------*/
6770 fprintf(outfile,"OR (%p) type (",tree);
6771 printTypeChain(tree->ftype,outfile);
6772 fprintf(outfile,")\n");
6773 ast_print(tree->left,outfile,indent+2);
6774 ast_print(tree->right,outfile,indent+2);
6776 /*------------------------------------------------------------------*/
6777 /*----------------------------*/
6779 /*----------------------------*/
6781 fprintf(outfile,"XOR (%p) type (",tree);
6782 printTypeChain(tree->ftype,outfile);
6783 fprintf(outfile,")\n");
6784 ast_print(tree->left,outfile,indent+2);
6785 ast_print(tree->right,outfile,indent+2);
6788 /*------------------------------------------------------------------*/
6789 /*----------------------------*/
6791 /*----------------------------*/
6793 fprintf(outfile,"DIV (%p) type (",tree);
6794 printTypeChain(tree->ftype,outfile);
6795 fprintf(outfile,")\n");
6796 ast_print(tree->left,outfile,indent+2);
6797 ast_print(tree->right,outfile,indent+2);
6799 /*------------------------------------------------------------------*/
6800 /*----------------------------*/
6802 /*----------------------------*/
6804 fprintf(outfile,"MOD (%p) type (",tree);
6805 printTypeChain(tree->ftype,outfile);
6806 fprintf(outfile,")\n");
6807 ast_print(tree->left,outfile,indent+2);
6808 ast_print(tree->right,outfile,indent+2);
6811 /*------------------------------------------------------------------*/
6812 /*----------------------------*/
6813 /* address dereference */
6814 /*----------------------------*/
6815 case '*': /* can be unary : if right is null then unary operation */
6817 fprintf(outfile,"DEREF (%p) type (",tree);
6818 printTypeChain(tree->ftype,outfile);
6819 fprintf(outfile,")\n");
6820 ast_print(tree->left,outfile,indent+2);
6823 /*------------------------------------------------------------------*/
6824 /*----------------------------*/
6825 /* multiplication */
6826 /*----------------------------*/
6827 fprintf(outfile,"MULT (%p) type (",tree);
6828 printTypeChain(tree->ftype,outfile);
6829 fprintf(outfile,")\n");
6830 ast_print(tree->left,outfile,indent+2);
6831 ast_print(tree->right,outfile,indent+2);
6835 /*------------------------------------------------------------------*/
6836 /*----------------------------*/
6837 /* unary '+' operator */
6838 /*----------------------------*/
6842 fprintf(outfile,"UPLUS (%p) type (",tree);
6843 printTypeChain(tree->ftype,outfile);
6844 fprintf(outfile,")\n");
6845 ast_print(tree->left,outfile,indent+2);
6847 /*------------------------------------------------------------------*/
6848 /*----------------------------*/
6850 /*----------------------------*/
6851 fprintf(outfile,"ADD (%p) type (",tree);
6852 printTypeChain(tree->ftype,outfile);
6853 fprintf(outfile,")\n");
6854 ast_print(tree->left,outfile,indent+2);
6855 ast_print(tree->right,outfile,indent+2);
6858 /*------------------------------------------------------------------*/
6859 /*----------------------------*/
6861 /*----------------------------*/
6862 case '-': /* can be unary */
6864 fprintf(outfile,"UMINUS (%p) type (",tree);
6865 printTypeChain(tree->ftype,outfile);
6866 fprintf(outfile,")\n");
6867 ast_print(tree->left,outfile,indent+2);
6869 /*------------------------------------------------------------------*/
6870 /*----------------------------*/
6872 /*----------------------------*/
6873 fprintf(outfile,"SUB (%p) type (",tree);
6874 printTypeChain(tree->ftype,outfile);
6875 fprintf(outfile,")\n");
6876 ast_print(tree->left,outfile,indent+2);
6877 ast_print(tree->right,outfile,indent+2);
6880 /*------------------------------------------------------------------*/
6881 /*----------------------------*/
6883 /*----------------------------*/
6885 fprintf(outfile,"COMPL (%p) type (",tree);
6886 printTypeChain(tree->ftype,outfile);
6887 fprintf(outfile,")\n");
6888 ast_print(tree->left,outfile,indent+2);
6890 /*------------------------------------------------------------------*/
6891 /*----------------------------*/
6893 /*----------------------------*/
6895 fprintf(outfile,"NOT (%p) type (",tree);
6896 printTypeChain(tree->ftype,outfile);
6897 fprintf(outfile,")\n");
6898 ast_print(tree->left,outfile,indent+2);
6900 /*------------------------------------------------------------------*/
6901 /*----------------------------*/
6903 /*----------------------------*/
6905 fprintf(outfile,"RRC (%p) type (",tree);
6906 printTypeChain(tree->ftype,outfile);
6907 fprintf(outfile,")\n");
6908 ast_print(tree->left,outfile,indent+2);
6912 fprintf(outfile,"RLC (%p) type (",tree);
6913 printTypeChain(tree->ftype,outfile);
6914 fprintf(outfile,")\n");
6915 ast_print(tree->left,outfile,indent+2);
6918 fprintf(outfile,"SWAP (%p) type (",tree);
6919 printTypeChain(tree->ftype,outfile);
6920 fprintf(outfile,")\n");
6921 ast_print(tree->left,outfile,indent+2);
6924 fprintf(outfile,"GETHBIT (%p) type (",tree);
6925 printTypeChain(tree->ftype,outfile);
6926 fprintf(outfile,")\n");
6927 ast_print(tree->left,outfile,indent+2);
6930 fprintf(outfile,"GETABIT (%p) type (",tree);
6931 printTypeChain(tree->ftype,outfile);
6932 fprintf(outfile,")\n");
6933 ast_print(tree->left,outfile,indent+2);
6934 ast_print(tree->right,outfile,indent+2);
6937 fprintf(outfile,"GETBYTE (%p) type (",tree);
6938 printTypeChain(tree->ftype,outfile);
6939 fprintf(outfile,")\n");
6940 ast_print(tree->left,outfile,indent+2);
6941 ast_print(tree->right,outfile,indent+2);
6944 fprintf(outfile,"GETWORD (%p) type (",tree);
6945 printTypeChain(tree->ftype,outfile);
6946 fprintf(outfile,")\n");
6947 ast_print(tree->left,outfile,indent+2);
6948 ast_print(tree->right,outfile,indent+2);
6951 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6952 printTypeChain(tree->ftype,outfile);
6953 fprintf(outfile,")\n");
6954 ast_print(tree->left,outfile,indent+2);
6955 ast_print(tree->right,outfile,indent+2);
6958 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6959 printTypeChain(tree->ftype,outfile);
6960 fprintf(outfile,")\n");
6961 ast_print(tree->left,outfile,indent+2);
6962 ast_print(tree->right,outfile,indent+2);
6964 /*------------------------------------------------------------------*/
6965 /*----------------------------*/
6967 /*----------------------------*/
6968 case CAST: /* change the type */
6969 fprintf(outfile,"CAST (%p) from type (",tree);
6970 printTypeChain(tree->right->ftype,outfile);
6971 fprintf(outfile,") to type (");
6972 printTypeChain(tree->ftype,outfile);
6973 fprintf(outfile,")\n");
6974 ast_print(tree->right,outfile,indent+2);
6978 fprintf(outfile,"ANDAND (%p) type (",tree);
6979 printTypeChain(tree->ftype,outfile);
6980 fprintf(outfile,")\n");
6981 ast_print(tree->left,outfile,indent+2);
6982 ast_print(tree->right,outfile,indent+2);
6985 fprintf(outfile,"OROR (%p) type (",tree);
6986 printTypeChain(tree->ftype,outfile);
6987 fprintf(outfile,")\n");
6988 ast_print(tree->left,outfile,indent+2);
6989 ast_print(tree->right,outfile,indent+2);
6992 /*------------------------------------------------------------------*/
6993 /*----------------------------*/
6994 /* comparison operators */
6995 /*----------------------------*/
6997 fprintf(outfile,"GT(>) (%p) type (",tree);
6998 printTypeChain(tree->ftype,outfile);
6999 fprintf(outfile,")\n");
7000 ast_print(tree->left,outfile,indent+2);
7001 ast_print(tree->right,outfile,indent+2);
7004 fprintf(outfile,"LT(<) (%p) type (",tree);
7005 printTypeChain(tree->ftype,outfile);
7006 fprintf(outfile,")\n");
7007 ast_print(tree->left,outfile,indent+2);
7008 ast_print(tree->right,outfile,indent+2);
7011 fprintf(outfile,"LE(<=) (%p) type (",tree);
7012 printTypeChain(tree->ftype,outfile);
7013 fprintf(outfile,")\n");
7014 ast_print(tree->left,outfile,indent+2);
7015 ast_print(tree->right,outfile,indent+2);
7018 fprintf(outfile,"GE(>=) (%p) type (",tree);
7019 printTypeChain(tree->ftype,outfile);
7020 fprintf(outfile,")\n");
7021 ast_print(tree->left,outfile,indent+2);
7022 ast_print(tree->right,outfile,indent+2);
7025 fprintf(outfile,"EQ(==) (%p) type (",tree);
7026 printTypeChain(tree->ftype,outfile);
7027 fprintf(outfile,")\n");
7028 ast_print(tree->left,outfile,indent+2);
7029 ast_print(tree->right,outfile,indent+2);
7032 fprintf(outfile,"NE(!=) (%p) type (",tree);
7033 printTypeChain(tree->ftype,outfile);
7034 fprintf(outfile,")\n");
7035 ast_print(tree->left,outfile,indent+2);
7036 ast_print(tree->right,outfile,indent+2);
7037 /*------------------------------------------------------------------*/
7038 /*----------------------------*/
7040 /*----------------------------*/
7041 case SIZEOF: /* evaluate wihout code generation */
7042 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7045 /*------------------------------------------------------------------*/
7046 /*----------------------------*/
7047 /* conditional operator '?' */
7048 /*----------------------------*/
7050 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7051 printTypeChain(tree->ftype,outfile);
7052 fprintf(outfile,")\n");
7053 ast_print(tree->left,outfile,indent+2);
7054 ast_print(tree->right,outfile,indent+2);
7058 fprintf(outfile,"COLON(:) (%p) type (",tree);
7059 printTypeChain(tree->ftype,outfile);
7060 fprintf(outfile,")\n");
7061 ast_print(tree->left,outfile,indent+2);
7062 ast_print(tree->right,outfile,indent+2);
7065 /*------------------------------------------------------------------*/
7066 /*----------------------------*/
7067 /* assignment operators */
7068 /*----------------------------*/
7070 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7071 printTypeChain(tree->ftype,outfile);
7072 fprintf(outfile,")\n");
7073 ast_print(tree->left,outfile,indent+2);
7074 ast_print(tree->right,outfile,indent+2);
7077 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7078 printTypeChain(tree->ftype,outfile);
7079 fprintf(outfile,")\n");
7080 ast_print(tree->left,outfile,indent+2);
7081 ast_print(tree->right,outfile,indent+2);
7084 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7085 printTypeChain(tree->ftype,outfile);
7086 fprintf(outfile,")\n");
7087 ast_print(tree->left,outfile,indent+2);
7088 ast_print(tree->right,outfile,indent+2);
7091 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7092 printTypeChain(tree->ftype,outfile);
7093 fprintf(outfile,")\n");
7094 ast_print(tree->left,outfile,indent+2);
7095 ast_print(tree->right,outfile,indent+2);
7098 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7099 printTypeChain(tree->ftype,outfile);
7100 fprintf(outfile,")\n");
7101 ast_print(tree->left,outfile,indent+2);
7102 ast_print(tree->right,outfile,indent+2);
7105 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7106 printTypeChain(tree->ftype,outfile);
7107 fprintf(outfile,")\n");
7108 ast_print(tree->left,outfile,indent+2);
7109 ast_print(tree->right,outfile,indent+2);
7112 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7113 printTypeChain(tree->ftype,outfile);
7114 fprintf(outfile,")\n");
7115 ast_print(tree->left,outfile,indent+2);
7116 ast_print(tree->right,outfile,indent+2);
7118 /*------------------------------------------------------------------*/
7119 /*----------------------------*/
7121 /*----------------------------*/
7123 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7124 printTypeChain(tree->ftype,outfile);
7125 fprintf(outfile,")\n");
7126 ast_print(tree->left,outfile,indent+2);
7127 ast_print(tree->right,outfile,indent+2);
7129 /*------------------------------------------------------------------*/
7130 /*----------------------------*/
7132 /*----------------------------*/
7134 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7135 printTypeChain(tree->ftype,outfile);
7136 fprintf(outfile,")\n");
7137 ast_print(tree->left,outfile,indent+2);
7138 ast_print(tree->right,outfile,indent+2);
7140 /*------------------------------------------------------------------*/
7141 /*----------------------------*/
7142 /* straight assignemnt */
7143 /*----------------------------*/
7145 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7146 printTypeChain(tree->ftype,outfile);
7147 fprintf(outfile,")\n");
7148 ast_print(tree->left,outfile,indent+2);
7149 ast_print(tree->right,outfile,indent+2);
7151 /*------------------------------------------------------------------*/
7152 /*----------------------------*/
7153 /* comma operator */
7154 /*----------------------------*/
7156 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7157 printTypeChain(tree->ftype,outfile);
7158 fprintf(outfile,")\n");
7159 ast_print(tree->left,outfile,indent+2);
7160 ast_print(tree->right,outfile,indent+2);
7162 /*------------------------------------------------------------------*/
7163 /*----------------------------*/
7165 /*----------------------------*/
7168 fprintf(outfile,"CALL (%p) type (",tree);
7169 printTypeChain(tree->ftype,outfile);
7170 fprintf(outfile,")\n");
7171 ast_print(tree->left,outfile,indent+2);
7172 ast_print(tree->right,outfile,indent+2);
7175 fprintf(outfile,"PARMS\n");
7176 ast_print(tree->left,outfile,indent+2);
7177 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7178 ast_print(tree->right,outfile,indent+2);
7181 /*------------------------------------------------------------------*/
7182 /*----------------------------*/
7183 /* return statement */
7184 /*----------------------------*/
7186 fprintf(outfile,"RETURN (%p) type (",tree);
7188 printTypeChain(tree->right->ftype,outfile);
7190 fprintf(outfile,")\n");
7191 ast_print(tree->right,outfile,indent+2);
7193 /*------------------------------------------------------------------*/
7194 /*----------------------------*/
7195 /* label statement */
7196 /*----------------------------*/
7198 fprintf(outfile,"LABEL (%p)\n",tree);
7199 ast_print(tree->left,outfile,indent+2);
7200 ast_print(tree->right,outfile,indent);
7202 /*------------------------------------------------------------------*/
7203 /*----------------------------*/
7204 /* switch statement */
7205 /*----------------------------*/
7209 fprintf(outfile,"SWITCH (%p) ",tree);
7210 ast_print(tree->left,outfile,0);
7211 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7212 INDENT(indent+2,outfile);
7213 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7214 (int) ulFromVal(val),
7215 tree->values.switchVals.swNum,
7216 (int) ulFromVal(val));
7218 ast_print(tree->right,outfile,indent);
7221 /*------------------------------------------------------------------*/
7222 /*----------------------------*/
7224 /*----------------------------*/
7226 fprintf(outfile,"IF (%p) \n",tree);
7227 ast_print(tree->left,outfile,indent+2);
7228 if (tree->trueLabel) {
7229 INDENT(indent+2,outfile);
7230 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7232 if (tree->falseLabel) {
7233 INDENT(indent+2,outfile);
7234 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7236 ast_print(tree->right,outfile,indent+2);
7238 /*----------------------------*/
7239 /* goto Statement */
7240 /*----------------------------*/
7242 fprintf(outfile,"GOTO (%p) \n",tree);
7243 ast_print(tree->left,outfile,indent+2);
7244 fprintf(outfile,"\n");
7246 /*------------------------------------------------------------------*/
7247 /*----------------------------*/
7249 /*----------------------------*/
7251 fprintf(outfile,"FOR (%p) \n",tree);
7252 if (AST_FOR( tree, initExpr)) {
7253 INDENT(indent+2,outfile);
7254 fprintf(outfile,"INIT EXPR ");
7255 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7257 if (AST_FOR( tree, condExpr)) {
7258 INDENT(indent+2,outfile);
7259 fprintf(outfile,"COND EXPR ");
7260 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7262 if (AST_FOR( tree, loopExpr)) {
7263 INDENT(indent+2,outfile);
7264 fprintf(outfile,"LOOP EXPR ");
7265 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7267 fprintf(outfile,"FOR LOOP BODY \n");
7268 ast_print(tree->left,outfile,indent+2);
7271 fprintf(outfile,"CRITICAL (%p) \n",tree);
7272 ast_print(tree->left,outfile,indent+2);
7280 ast_print(t,stdout,0);
7283 /*-----------------------------------------------------------------*/
7284 /* astErrors : returns non-zero if errors present in tree */
7285 /*-----------------------------------------------------------------*/
7286 int astErrors(ast *t)
7295 if (t->type == EX_VALUE
7296 && t->opval.val->sym
7297 && t->opval.val->sym->undefined)
7300 errors += astErrors(t->left);
7301 errors += astErrors(t->right);