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)
87 static int oldLineno = 0;
89 ex = Safe_alloc ( sizeof (ast));
92 ex->lineno = (noLineno ? oldLineno : lexLineno);
93 ex->filename = lexFilename;
94 ex->level = NestLevel;
95 ex->block = currBlockno;
96 ex->initMode = inInitMode;
97 ex->seqPoint = seqPointNo;
102 newAst_VALUE (value * val)
104 ast *ex = newAst_ (EX_VALUE);
110 newAst_OP (unsigned op)
112 ast *ex = newAst_ (EX_OP);
118 newAst_LINK (sym_link * val)
120 ast *ex = newAst_ (EX_LINK);
125 /*-----------------------------------------------------------------*/
126 /* newNode - creates a new node */
127 /*-----------------------------------------------------------------*/
129 newNode (long op, ast * left, ast * right)
140 /*-----------------------------------------------------------------*/
141 /* newIfxNode - creates a new Ifx Node */
142 /*-----------------------------------------------------------------*/
144 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
148 /* if this is a literal then we already know the result */
149 if (condAst->etype && IS_LITERAL (condAst->etype))
151 /* then depending on the expression value */
152 if (floatFromVal (condAst->opval.val))
153 ifxNode = newNode (GOTO,
154 newAst_VALUE (symbolVal (trueLabel)),
157 ifxNode = newNode (GOTO,
158 newAst_VALUE (symbolVal (falseLabel)),
163 ifxNode = newNode (IFX, condAst, NULL);
164 ifxNode->trueLabel = trueLabel;
165 ifxNode->falseLabel = falseLabel;
171 /*-----------------------------------------------------------------*/
172 /* copyAstValues - copies value portion of ast if needed */
173 /*-----------------------------------------------------------------*/
175 copyAstValues (ast * dest, ast * src)
177 switch (src->opval.op)
180 dest->values.sym = copySymbolChain (src->values.sym);
184 dest->values.switchVals.swVals =
185 copyValue (src->values.switchVals.swVals);
186 dest->values.switchVals.swDefault =
187 src->values.switchVals.swDefault;
188 dest->values.switchVals.swNum =
189 src->values.switchVals.swNum;
193 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
197 dest->values.constlist = copyLiteralList(src->values.constlist);
201 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
202 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
203 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
204 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
205 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
206 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
207 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
212 /*-----------------------------------------------------------------*/
213 /* copyAst - makes a copy of a given astession */
214 /*-----------------------------------------------------------------*/
223 dest = Safe_alloc ( sizeof (ast));
225 dest->type = src->type;
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 /* setAstLineno - walks a ast tree & sets the line number */
621 /*-----------------------------------------------------------------*/
622 int setAstLineno (ast * tree, int lineno)
627 tree->lineno = lineno;
628 setAstLineno (tree->left, lineno);
629 setAstLineno (tree->right, lineno);
633 /*-----------------------------------------------------------------*/
634 /* funcOfType :- function of type with name */
635 /*-----------------------------------------------------------------*/
637 funcOfType (char *name, sym_link * type, sym_link * argType,
641 /* create the symbol */
642 sym = newSymbol (name, 0);
644 /* setup return value */
645 sym->type = newLink (DECLARATOR);
646 DCL_TYPE (sym->type) = FUNCTION;
647 sym->type->next = copyLinkChain (type);
648 sym->etype = getSpec (sym->type);
649 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
651 /* if arguments required */
655 args = FUNC_ARGS(sym->type) = newValue ();
659 args->type = copyLinkChain (argType);
660 args->etype = getSpec (args->type);
661 SPEC_EXTR(args->etype)=1;
664 args = args->next = newValue ();
671 allocVariables (sym);
676 /*-----------------------------------------------------------------*/
677 /* funcOfTypeVarg :- function of type with name and argtype */
678 /*-----------------------------------------------------------------*/
680 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
685 /* create the symbol */
686 sym = newSymbol (name, 0);
688 /* setup return value */
689 sym->type = newLink (DECLARATOR);
690 DCL_TYPE (sym->type) = FUNCTION;
691 sym->type->next = typeFromStr(rtype);
692 sym->etype = getSpec (sym->type);
694 /* if arguments required */
697 args = FUNC_ARGS(sym->type) = newValue ();
699 for ( i = 0 ; i < nArgs ; i++ ) {
700 args->type = typeFromStr(atypes[i]);
701 args->etype = getSpec (args->type);
702 SPEC_EXTR(args->etype)=1;
703 if ((i + 1) == nArgs) break;
704 args = args->next = newValue ();
711 allocVariables (sym);
716 /*-----------------------------------------------------------------*/
717 /* reverseParms - will reverse a parameter tree */
718 /*-----------------------------------------------------------------*/
720 reverseParms (ast * ptree)
726 /* top down if we find a nonParm tree then quit */
727 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
729 /* The various functions expect the parameter tree to be right heavy. */
730 /* Rotate the tree to be left heavy so that after reversal it is */
731 /* right heavy again. */
732 while ((ttree = ptree->right) && ttree->type == EX_OP &&
733 ttree->opval.op == PARAM)
735 ptree->right = ttree->right;
736 ttree->right = ttree->left;
737 ttree->left = ptree->left;
743 ptree->left = ptree->right;
744 ptree->right = ttree;
746 reverseParms (ptree->left);
747 reverseParms (ptree->right);
753 /*-----------------------------------------------------------------*/
754 /* processParms - makes sure the parameters are okay and do some */
755 /* processing with them */
756 /*-----------------------------------------------------------------*/
758 processParms (ast *func,
761 int *parmNumber, /* unused, although updated */
764 RESULT_TYPE resultType;
767 /* if none of them exist */
768 if (!defParm && !*actParm)
773 if (getenv("DEBUG_SANITY"))
775 fprintf (stderr, "processParms: %s ", defParm->name);
777 /* make sure the type is complete and sane */
778 checkTypeSanity(defParm->etype, defParm->name);
781 if (IS_CODEPTR (func->ftype))
782 functype = func->ftype->next;
784 functype = func->ftype;
786 /* if the function is being called via a pointer & */
787 /* it has not been defined reentrant then we cannot */
788 /* have parameters */
789 /* PIC16 port can... */
790 if (!TARGET_IS_PIC16)
792 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
794 werror (E_NONRENT_ARGS);
800 /* if defined parameters ended but actual parameters */
801 /* exist and this is not defined as a variable arg */
802 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
804 werror (E_TOO_MANY_PARMS);
808 /* if defined parameters present but no actual parameters */
809 if (defParm && !*actParm)
811 werror (E_TOO_FEW_PARMS);
815 /* if this is a PARAM node then match left & right */
816 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
818 (*actParm)->decorated = 1;
819 return (processParms (func, defParm,
820 &(*actParm)->left, parmNumber, FALSE) ||
821 processParms (func, defParm ? defParm->next : NULL,
822 &(*actParm)->right, parmNumber, rightmost));
824 else if (defParm) /* not vararg */
826 /* If we have found a value node by following only right-hand links,
827 * then we know that there are no more values after us.
829 * Therefore, if there are more defined parameters, the caller didn't
832 if (rightmost && defParm->next)
834 werror (E_TOO_FEW_PARMS);
839 /* decorate parameter */
840 resultType = defParm ? getResultTypeFromType (defParm->type) :
842 *actParm = decorateType (*actParm, resultType);
844 if (IS_VOID((*actParm)->ftype))
846 werror (E_VOID_VALUE_USED);
850 /* If this is a varargs function... */
851 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
856 if (IS_CAST_OP (*actParm)
857 || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
859 /* Parameter was explicitly typecast; don't touch it. */
863 ftype = (*actParm)->ftype;
865 /* If it's a char, upcast to int. */
866 if (IS_INTEGRAL (ftype)
867 && (getSize (ftype) < (unsigned) INTSIZE))
869 newType = newAst_LINK(INTTYPE);
872 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
874 newType = newAst_LINK (copyLinkChain(ftype));
875 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
878 if (IS_AGGREGATE (ftype))
880 newType = newAst_LINK (copyLinkChain (ftype));
881 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
886 /* cast required; change this op to a cast. */
887 (*actParm)->decorated = 0;
888 *actParm = newNode (CAST, newType, *actParm);
889 (*actParm)->lineno = (*actParm)->right->lineno;
891 decorateType (*actParm, RESULT_TYPE_NONE);
896 /* if defined parameters ended but actual has not & */
898 if (!defParm && *actParm &&
899 (options.stackAuto || IFFUNC_ISREENT (functype)))
902 resolveSymbols (*actParm);
904 /* the parameter type must be at least castable */
905 if (compareType (defParm->type, (*actParm)->ftype) == 0)
907 werror (E_INCOMPAT_TYPES);
908 printFromToType ((*actParm)->ftype, defParm->type);
912 /* if the parameter is castable then add the cast */
913 if (compareType (defParm->type, (*actParm)->ftype) < 0)
917 resultType = getResultTypeFromType (defParm->etype);
918 pTree = resolveSymbols (copyAst (*actParm));
920 /* now change the current one to a cast */
921 (*actParm)->type = EX_OP;
922 (*actParm)->opval.op = CAST;
923 (*actParm)->left = newAst_LINK (defParm->type);
924 (*actParm)->right = pTree;
925 (*actParm)->decorated = 0; /* force typechecking */
926 decorateType (*actParm, resultType);
929 /* make a copy and change the regparm type to the defined parm */
930 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
931 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
932 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
934 /* if the function is being called via a pointer & */
935 /* this parameter is not passed in registers */
936 /* then the function must be defined reentrant */
937 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
938 !IFFUNC_ISREENT (functype) && !options.stackAuto)
940 werror (E_NONRENT_ARGS);
949 /*-----------------------------------------------------------------*/
950 /* createIvalType - generates ival for basic types */
951 /*-----------------------------------------------------------------*/
953 createIvalType (ast * sym, sym_link * type, initList * ilist)
957 /* if initList is deep */
958 if (ilist->type == INIT_DEEP)
959 ilist = ilist->init.deep;
961 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
962 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
965 /*-----------------------------------------------------------------*/
966 /* createIvalStruct - generates initial value for structures */
967 /*-----------------------------------------------------------------*/
969 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
976 sflds = SPEC_STRUCT (type)->fields;
977 if (ilist->type != INIT_DEEP)
979 werror (E_INIT_STRUCT, "");
983 iloop = ilist->init.deep;
985 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
987 /* if we have come to end */
991 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
992 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
993 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
994 iloop, rast, rootValue)),
1000 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1001 W_EXCESS_INITIALIZERS, "struct",
1002 sym->opval.val->sym->name);
1009 /*-----------------------------------------------------------------*/
1010 /* createIvalArray - generates code for array initialization */
1011 /*-----------------------------------------------------------------*/
1013 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1017 int lcnt = 0, size = 0;
1018 literalList *literalL;
1020 /* take care of the special case */
1021 /* array of characters can be init */
1023 if (IS_CHAR (type->next))
1024 if ((rast = createIvalCharPtr (sym,
1026 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1029 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1031 /* not the special case */
1032 if (ilist->type != INIT_DEEP)
1034 werror (E_INIT_STRUCT, "");
1038 iloop = ilist->init.deep;
1039 lcnt = DCL_ELEM (type);
1041 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1045 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1047 rast = newNode(ARRAYINIT, aSym, NULL);
1048 rast->values.constlist = literalL;
1050 // Make sure size is set to length of initializer list.
1054 iloop = iloop->next;
1057 if (lcnt && size > lcnt)
1059 // Array size was specified, and we have more initializers than needed.
1060 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1061 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1070 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1071 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1072 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1073 iloop = (iloop ? iloop->next : NULL);
1079 /* no of elements given and we */
1080 /* have generated for all of them */
1083 // is this a better way? at least it won't crash
1084 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1085 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1092 /* if we have not been given a size */
1093 if (!DCL_ELEM (type))
1095 /* check, if it's a flexible array */
1096 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1097 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1099 DCL_ELEM (type) = size;
1102 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1106 /*-----------------------------------------------------------------*/
1107 /* createIvalCharPtr - generates initial values for char pointers */
1108 /*-----------------------------------------------------------------*/
1110 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1115 /* if this is a pointer & right is a literal array then */
1116 /* just assignment will do */
1117 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1118 SPEC_SCLS (iexpr->etype) == S_CODE)
1119 && IS_ARRAY (iexpr->ftype)))
1120 return newNode ('=', sym, iexpr);
1122 /* left side is an array so we have to assign each element */
1123 if ((IS_LITERAL (iexpr->etype) ||
1124 SPEC_SCLS (iexpr->etype) == S_CODE)
1125 && IS_ARRAY (iexpr->ftype))
1127 /* for each character generate an assignment */
1128 /* to the array element */
1129 char *s = SPEC_CVAL (iexpr->etype).v_char;
1131 unsigned int symsize = getSize (type);
1133 size = getSize (iexpr->ftype);
1134 if (symsize && size>symsize)
1136 if (size>(symsize+1))
1138 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1140 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1146 for (i=0;i<size;i++)
1148 rast = newNode (NULLOP,
1152 newAst_VALUE (valueFromLit ((float) i))),
1153 newAst_VALUE (valueFromLit (*s))));
1157 // now WE don't need iexpr's symbol anymore
1158 freeStringSymbol(AST_SYMBOL(iexpr));
1160 /* if we have not been given a size */
1161 if (!DCL_ELEM (type))
1163 /* check, if it's a flexible array */
1164 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1165 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1167 DCL_ELEM (type) = size;
1170 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1176 /*-----------------------------------------------------------------*/
1177 /* createIvalPtr - generates initial value for pointers */
1178 /*-----------------------------------------------------------------*/
1180 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1186 if (ilist->type == INIT_DEEP)
1187 ilist = ilist->init.deep;
1189 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1191 /* if character pointer */
1192 if (IS_CHAR (type->next))
1193 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1196 return newNode ('=', sym, iexpr);
1199 /*-----------------------------------------------------------------*/
1200 /* createIval - generates code for initial value */
1201 /*-----------------------------------------------------------------*/
1203 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1210 /* if structure then */
1211 if (IS_STRUCT (type))
1212 rast = createIvalStruct (sym, type, ilist, rootValue);
1214 /* if this is a pointer */
1216 rast = createIvalPtr (sym, type, ilist, rootValue);
1218 /* if this is an array */
1219 if (IS_ARRAY (type))
1220 rast = createIvalArray (sym, type, ilist, rootValue);
1222 /* if type is SPECIFIER */
1224 rast = createIvalType (sym, type, ilist);
1227 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1229 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1232 /*-----------------------------------------------------------------*/
1233 /* initAggregates - initialises aggregate variables with initv */
1234 /*-----------------------------------------------------------------*/
1235 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1236 ast *newAst = newAst_VALUE (symbolVal (sym));
1237 return createIval (newAst, sym->type, ival, wid, newAst);
1240 /*-----------------------------------------------------------------*/
1241 /* gatherAutoInit - creates assignment expressions for initial */
1243 /*-----------------------------------------------------------------*/
1245 gatherAutoInit (symbol * autoChain)
1252 for (sym = autoChain; sym; sym = sym->next)
1255 /* resolve the symbols in the ival */
1257 resolveIvalSym (sym->ival, sym->type);
1260 /* if we are PIC16 port,
1261 * and this is a static,
1262 * and have initial value,
1263 * and not S_CODE, don't emit in gs segment,
1264 * but allow glue.c:pic16emitRegularMap to put symbol
1265 * in idata section */
1266 if(TARGET_IS_PIC16 &&
1267 IS_STATIC (sym->etype) && sym->ival
1268 && SPEC_SCLS(sym->etype) != S_CODE) {
1269 SPEC_SCLS (sym->etype) = S_DATA;
1274 /* if this is a static variable & has an */
1275 /* initial value the code needs to be lifted */
1276 /* here to the main portion since they can be */
1277 /* initialised only once at the start */
1278 if (IS_STATIC (sym->etype) && sym->ival &&
1279 SPEC_SCLS (sym->etype) != S_CODE)
1283 /* insert the symbol into the symbol table */
1284 /* with level = 0 & name = rname */
1285 newSym = copySymbol (sym);
1286 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1288 /* now lift the code to main */
1289 if (IS_AGGREGATE (sym->type)) {
1290 work = initAggregates (sym, sym->ival, NULL);
1292 if (getNelements(sym->type, sym->ival)>1) {
1293 werrorfl (sym->fileDef, sym->lineDef,
1294 W_EXCESS_INITIALIZERS, "scalar",
1297 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1298 list2expr (sym->ival));
1301 setAstLineno (work, sym->lineDef);
1305 staticAutos = newNode (NULLOP, staticAutos, work);
1312 /* if there is an initial value */
1313 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1315 initList *ilist=sym->ival;
1317 while (ilist->type == INIT_DEEP) {
1318 ilist = ilist->init.deep;
1321 /* update lineno for error msg */
1322 lineno = sym->lineDef;
1323 setAstLineno (ilist->init.node, sym->lineDef);
1325 if (IS_AGGREGATE (sym->type)) {
1326 work = initAggregates (sym, sym->ival, NULL);
1328 if (getNelements(sym->type, sym->ival)>1) {
1329 werrorfl (sym->fileDef, sym->lineDef,
1330 W_EXCESS_INITIALIZERS, "scalar",
1333 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1334 list2expr (sym->ival));
1338 setAstLineno (work, sym->lineDef);
1342 init = newNode (NULLOP, init, work);
1351 /*-----------------------------------------------------------------*/
1352 /* freeStringSymbol - delete a literal string if no more usage */
1353 /*-----------------------------------------------------------------*/
1354 void freeStringSymbol(symbol *sym) {
1355 /* make sure this is a literal string */
1356 assert (sym->isstrlit);
1357 if (--sym->isstrlit == 0) { // lower the usage count
1358 memmap *segment=SPEC_OCLS(sym->etype);
1360 deleteSetItem(&segment->syms, sym);
1365 /*-----------------------------------------------------------------*/
1366 /* stringToSymbol - creates a symbol from a literal string */
1367 /*-----------------------------------------------------------------*/
1369 stringToSymbol (value * val)
1371 char name[SDCC_NAME_MAX + 1];
1372 static int charLbl = 0;
1377 // have we heard this before?
1378 for (sp=statsg->syms; sp; sp=sp->next) {
1380 size = getSize (sym->type);
1381 if (sym->isstrlit && size == getSize (val->type) &&
1382 !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
1383 // yes, this is old news. Don't publish it again.
1384 sym->isstrlit++; // but raise the usage count
1385 return symbolVal(sym);
1389 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1390 sym = newSymbol (name, 0); /* make it @ level 0 */
1391 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1393 /* copy the type from the value passed */
1394 sym->type = copyLinkChain (val->type);
1395 sym->etype = getSpec (sym->type);
1396 /* change to storage class & output class */
1397 SPEC_SCLS (sym->etype) = S_CODE;
1398 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1399 SPEC_STAT (sym->etype) = 1;
1400 /* make the level & block = 0 */
1401 sym->block = sym->level = 0;
1403 /* create an ival */
1404 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1409 allocVariables (sym);
1412 return symbolVal (sym);
1416 /*-----------------------------------------------------------------*/
1417 /* processBlockVars - will go thru the ast looking for block if */
1418 /* a block is found then will allocate the syms */
1419 /* will also gather the auto inits present */
1420 /*-----------------------------------------------------------------*/
1422 processBlockVars (ast * tree, int *stack, int action)
1427 /* if this is a block */
1428 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1432 if (action == ALLOCATE)
1434 *stack += allocVariables (tree->values.sym);
1435 autoInit = gatherAutoInit (tree->values.sym);
1437 /* if there are auto inits then do them */
1439 tree->left = newNode (NULLOP, autoInit, tree->left);
1441 else /* action is deallocate */
1442 deallocLocal (tree->values.sym);
1445 processBlockVars (tree->left, stack, action);
1446 processBlockVars (tree->right, stack, action);
1451 /*-------------------------------------------------------------*/
1452 /* constExprTree - returns TRUE if this tree is a constant */
1454 /*-------------------------------------------------------------*/
1455 bool constExprTree (ast *cexpr) {
1461 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1463 switch (cexpr->type)
1466 if (IS_AST_LIT_VALUE(cexpr)) {
1467 // this is a literal
1470 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1471 // a function's address will never change
1474 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1475 // an array's address will never change
1478 if (IS_AST_SYM_VALUE(cexpr) &&
1479 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1480 // a symbol in code space will never change
1481 // This is only for the 'char *s="hallo"' case and will have to leave
1482 //printf(" code space symbol");
1487 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1488 "unexpected link in expression tree\n");
1491 if (cexpr->opval.op==ARRAYINIT) {
1492 // this is a list of literals
1495 if (cexpr->opval.op=='=') {
1496 return constExprTree(cexpr->right);
1498 if (cexpr->opval.op==CAST) {
1499 // cast ignored, maybe we should throw a warning here?
1500 return constExprTree(cexpr->right);
1502 if (cexpr->opval.op=='&') {
1505 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1508 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1513 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1518 /*-----------------------------------------------------------------*/
1519 /* constExprValue - returns the value of a constant expression */
1520 /* or NULL if it is not a constant expression */
1521 /*-----------------------------------------------------------------*/
1523 constExprValue (ast * cexpr, int check)
1525 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1527 /* if this is not a constant then */
1528 if (!IS_LITERAL (cexpr->ftype))
1530 /* then check if this is a literal array
1532 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1533 SPEC_CVAL (cexpr->etype).v_char &&
1534 IS_ARRAY (cexpr->ftype))
1536 value *val = valFromType (cexpr->ftype);
1537 SPEC_SCLS (val->etype) = S_LITERAL;
1538 val->sym = cexpr->opval.val->sym;
1539 val->sym->type = copyLinkChain (cexpr->ftype);
1540 val->sym->etype = getSpec (val->sym->type);
1541 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1545 /* if we are casting a literal value then */
1546 if (IS_AST_OP (cexpr) &&
1547 cexpr->opval.op == CAST &&
1548 IS_LITERAL (cexpr->right->ftype))
1550 return valCastLiteral (cexpr->ftype,
1551 floatFromVal (cexpr->right->opval.val));
1554 if (IS_AST_VALUE (cexpr))
1556 return cexpr->opval.val;
1560 werror (E_CONST_EXPECTED, "found expression");
1565 /* return the value */
1566 if (IS_AST_VALUE (cexpr))
1568 return cexpr->opval.val;
1573 /*-----------------------------------------------------------------*/
1574 /* isLabelInAst - will return true if a given label is found */
1575 /*-----------------------------------------------------------------*/
1577 isLabelInAst (symbol * label, ast * tree)
1579 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1582 if (IS_AST_OP (tree) &&
1583 tree->opval.op == LABEL &&
1584 isSymbolEqual (AST_SYMBOL (tree->left), label))
1587 return isLabelInAst (label, tree->right) &&
1588 isLabelInAst (label, tree->left);
1591 /*-----------------------------------------------------------------*/
1592 /* isLoopCountable - return true if the loop count can be determi- */
1593 /* -ned at compile time . */
1594 /*-----------------------------------------------------------------*/
1596 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1597 symbol ** sym, ast ** init, ast ** end)
1600 /* the loop is considered countable if the following
1601 conditions are true :-
1603 a) initExpr :- <sym> = <const>
1604 b) condExpr :- <sym> < <const1>
1605 c) loopExpr :- <sym> ++
1608 /* first check the initExpr */
1609 if (IS_AST_OP (initExpr) &&
1610 initExpr->opval.op == '=' && /* is assignment */
1611 IS_AST_SYM_VALUE (initExpr->left))
1612 { /* left is a symbol */
1614 *sym = AST_SYMBOL (initExpr->left);
1615 *init = initExpr->right;
1620 /* don't reverse loop with volatile counter */
1621 if (IS_VOLATILE ((*sym)->type))
1624 /* for now the symbol has to be of
1626 if (!IS_INTEGRAL ((*sym)->type))
1629 /* now check condExpr */
1630 if (IS_AST_OP (condExpr))
1633 switch (condExpr->opval.op)
1636 if (IS_AST_SYM_VALUE (condExpr->left) &&
1637 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1638 IS_AST_LIT_VALUE (condExpr->right))
1640 *end = condExpr->right;
1646 if (IS_AST_OP (condExpr->left) &&
1647 condExpr->left->opval.op == '>' &&
1648 IS_AST_LIT_VALUE (condExpr->left->right) &&
1649 IS_AST_SYM_VALUE (condExpr->left->left) &&
1650 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1653 *end = newNode ('+', condExpr->left->right,
1654 newAst_VALUE (constCharVal (1)));
1667 /* check loop expression is of the form <sym>++ */
1668 if (!IS_AST_OP (loopExpr))
1671 /* check if <sym> ++ */
1672 if (loopExpr->opval.op == INC_OP)
1678 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1679 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1686 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1687 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1695 if (loopExpr->opval.op == ADD_ASSIGN)
1698 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1699 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1700 IS_AST_LIT_VALUE (loopExpr->right) &&
1701 AST_ULONG_VALUE (loopExpr->right) != 1)
1709 /*-----------------------------------------------------------------*/
1710 /* astHasVolatile - returns true if ast contains any volatile */
1711 /*-----------------------------------------------------------------*/
1713 astHasVolatile (ast * tree)
1718 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1721 if (IS_AST_OP (tree))
1722 return astHasVolatile (tree->left) ||
1723 astHasVolatile (tree->right);
1728 /*-----------------------------------------------------------------*/
1729 /* astHasPointer - return true if the ast contains any ptr variable */
1730 /*-----------------------------------------------------------------*/
1732 astHasPointer (ast * tree)
1737 if (IS_AST_LINK (tree))
1740 /* if we hit an array expression then check
1741 only the left side */
1742 if (IS_AST_OP (tree) && tree->opval.op == '[')
1743 return astHasPointer (tree->left);
1745 if (IS_AST_VALUE (tree))
1746 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1748 return astHasPointer (tree->left) ||
1749 astHasPointer (tree->right);
1753 /*-----------------------------------------------------------------*/
1754 /* astHasSymbol - return true if the ast has the given symbol */
1755 /*-----------------------------------------------------------------*/
1757 astHasSymbol (ast * tree, symbol * sym)
1759 if (!tree || IS_AST_LINK (tree))
1762 if (IS_AST_VALUE (tree))
1764 if (IS_AST_SYM_VALUE (tree))
1765 return isSymbolEqual (AST_SYMBOL (tree), sym);
1770 return astHasSymbol (tree->left, sym) ||
1771 astHasSymbol (tree->right, sym);
1774 /*-----------------------------------------------------------------*/
1775 /* astHasDeref - return true if the ast has an indirect access */
1776 /*-----------------------------------------------------------------*/
1778 astHasDeref (ast * tree)
1780 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1783 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1785 return astHasDeref (tree->left) || astHasDeref (tree->right);
1788 /*-----------------------------------------------------------------*/
1789 /* isConformingBody - the loop body has to conform to a set of rules */
1790 /* for the loop to be considered reversible read on for rules */
1791 /*-----------------------------------------------------------------*/
1793 isConformingBody (ast * pbody, symbol * sym, ast * body)
1796 /* we are going to do a pre-order traversal of the
1797 tree && check for the following conditions. (essentially
1798 a set of very shallow tests )
1799 a) the sym passed does not participate in
1800 any arithmetic operation
1801 b) There are no function calls
1802 c) all jumps are within the body
1803 d) address of loop control variable not taken
1804 e) if an assignment has a pointer on the
1805 left hand side make sure right does not have
1806 loop control variable */
1808 /* if we reach the end or a leaf then true */
1809 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1812 /* if anything else is "volatile" */
1813 if (IS_VOLATILE (TETYPE (pbody)))
1816 /* we will walk the body in a pre-order traversal for
1818 switch (pbody->opval.op)
1820 /*------------------------------------------------------------------*/
1822 // if the loopvar is used as an index
1823 /* array op is commutative -- must check both left & right */
1824 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1827 return isConformingBody (pbody->right, sym, body)
1828 && isConformingBody (pbody->left, sym, body);
1830 /*------------------------------------------------------------------*/
1835 /*------------------------------------------------------------------*/
1839 /* sure we are not sym is not modified */
1841 IS_AST_SYM_VALUE (pbody->left) &&
1842 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1846 IS_AST_SYM_VALUE (pbody->right) &&
1847 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1852 /*------------------------------------------------------------------*/
1854 case '*': /* can be unary : if right is null then unary operation */
1859 /* if right is NULL then unary operation */
1860 /*------------------------------------------------------------------*/
1861 /*----------------------------*/
1863 /*----------------------------*/
1866 if (IS_AST_SYM_VALUE (pbody->left) &&
1867 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1870 return isConformingBody (pbody->left, sym, body);
1874 if (astHasSymbol (pbody->left, sym) ||
1875 astHasSymbol (pbody->right, sym))
1880 /*------------------------------------------------------------------*/
1891 if (IS_AST_SYM_VALUE (pbody->left) &&
1892 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1895 if (IS_AST_SYM_VALUE (pbody->right) &&
1896 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1899 return isConformingBody (pbody->left, sym, body) &&
1900 isConformingBody (pbody->right, sym, body);
1908 if (IS_AST_SYM_VALUE (pbody->left) &&
1909 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1911 return isConformingBody (pbody->left, sym, body);
1913 /*------------------------------------------------------------------*/
1925 case SIZEOF: /* evaluate wihout code generation */
1927 if (IS_AST_SYM_VALUE (pbody->left) &&
1928 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1931 if (IS_AST_SYM_VALUE (pbody->right) &&
1932 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1935 return isConformingBody (pbody->left, sym, body) &&
1936 isConformingBody (pbody->right, sym, body);
1938 /*------------------------------------------------------------------*/
1941 /* if left has a pointer & right has loop
1942 control variable then we cannot */
1943 if (astHasPointer (pbody->left) &&
1944 astHasSymbol (pbody->right, sym))
1946 if (astHasVolatile (pbody->left))
1949 if (IS_AST_SYM_VALUE (pbody->left)) {
1950 // if the loopvar has an assignment
1951 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1953 // if the loopvar is used in another (maybe conditional) block
1954 if (astHasSymbol (pbody->right, sym) &&
1955 (pbody->level >= body->level)) {
1960 if (astHasVolatile (pbody->left))
1963 if (astHasDeref(pbody->right)) return FALSE;
1965 return isConformingBody (pbody->left, sym, body) &&
1966 isConformingBody (pbody->right, sym, body);
1977 assert ("Parser should not have generated this\n");
1979 /*------------------------------------------------------------------*/
1980 /*----------------------------*/
1981 /* comma operator */
1982 /*----------------------------*/
1984 return isConformingBody (pbody->left, sym, body) &&
1985 isConformingBody (pbody->right, sym, body);
1987 /*------------------------------------------------------------------*/
1988 /*----------------------------*/
1990 /*----------------------------*/
1992 /* if local & not passed as paramater then ok */
1993 if (sym->level && !astHasSymbol(pbody->right,sym))
1997 /*------------------------------------------------------------------*/
1998 /*----------------------------*/
1999 /* return statement */
2000 /*----------------------------*/
2005 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2010 if (astHasSymbol (pbody->left, sym))
2017 return isConformingBody (pbody->left, sym, body) &&
2018 isConformingBody (pbody->right, sym, body);
2024 /*-----------------------------------------------------------------*/
2025 /* isLoopReversible - takes a for loop as input && returns true */
2026 /* if the for loop is reversible. If yes will set the value of */
2027 /* the loop control var & init value & termination value */
2028 /*-----------------------------------------------------------------*/
2030 isLoopReversible (ast * loop, symbol ** loopCntrl,
2031 ast ** init, ast ** end)
2033 /* if option says don't do it then don't */
2034 if (optimize.noLoopReverse)
2036 /* there are several tests to determine this */
2038 /* for loop has to be of the form
2039 for ( <sym> = <const1> ;
2040 [<sym> < <const2>] ;
2041 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2043 if (!isLoopCountable (AST_FOR (loop, initExpr),
2044 AST_FOR (loop, condExpr),
2045 AST_FOR (loop, loopExpr),
2046 loopCntrl, init, end))
2049 /* now do some serious checking on the body of the loop
2052 return isConformingBody (loop->left, *loopCntrl, loop->left);
2056 /*-----------------------------------------------------------------*/
2057 /* replLoopSym - replace the loop sym by loop sym -1 */
2058 /*-----------------------------------------------------------------*/
2060 replLoopSym (ast * body, symbol * sym)
2063 if (!body || IS_AST_LINK (body))
2066 if (IS_AST_SYM_VALUE (body))
2069 if (isSymbolEqual (AST_SYMBOL (body), sym))
2073 body->opval.op = '-';
2074 body->left = newAst_VALUE (symbolVal (sym));
2075 body->right = newAst_VALUE (constCharVal (1));
2083 replLoopSym (body->left, sym);
2084 replLoopSym (body->right, sym);
2088 /*-----------------------------------------------------------------*/
2089 /* reverseLoop - do the actual loop reversal */
2090 /*-----------------------------------------------------------------*/
2092 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2096 /* create the following tree
2101 if (sym) goto for_continue ;
2104 /* put it together piece by piece */
2105 rloop = newNode (NULLOP,
2106 createIf (newAst_VALUE (symbolVal (sym)),
2108 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2111 newAst_VALUE (symbolVal (sym)),
2114 replLoopSym (loop->left, sym);
2115 setAstLineno (rloop, init->lineno);
2117 rloop = newNode (NULLOP,
2119 newAst_VALUE (symbolVal (sym)),
2120 newNode ('-', end, init)),
2121 createLabel (AST_FOR (loop, continueLabel),
2125 newNode (SUB_ASSIGN,
2126 newAst_VALUE (symbolVal (sym)),
2127 newAst_VALUE (constCharVal (1))),
2130 rloop->lineno=init->lineno;
2131 return decorateType (rloop, RESULT_TYPE_NONE);
2135 /*-----------------------------------------------------------------*/
2136 /* searchLitOp - search tree (*ops only) for an ast with literal */
2137 /*-----------------------------------------------------------------*/
2139 searchLitOp (ast *tree, ast **parent, const char *ops)
2143 if (tree && optimize.global_cse)
2145 /* is there a literal operand? */
2147 IS_AST_OP(tree->right) &&
2148 tree->right->right &&
2149 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2151 if (IS_LITERAL (RTYPE (tree->right)) !=
2152 IS_LITERAL (LTYPE (tree->right)))
2154 tree->right->decorated = 0;
2155 tree->decorated = 0;
2159 ret = searchLitOp (tree->right, parent, ops);
2164 IS_AST_OP(tree->left) &&
2165 tree->left->right &&
2166 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2168 if (IS_LITERAL (RTYPE (tree->left)) !=
2169 IS_LITERAL (LTYPE (tree->left)))
2171 tree->left->decorated = 0;
2172 tree->decorated = 0;
2176 ret = searchLitOp (tree->left, parent, ops);
2184 /*-----------------------------------------------------------------*/
2185 /* getResultFromType */
2186 /*-----------------------------------------------------------------*/
2188 getResultTypeFromType (sym_link *type)
2190 /* type = getSpec (type); */
2192 return RESULT_TYPE_BIT;
2193 if (IS_BITFIELD (type))
2195 int blen = SPEC_BLEN (type);
2198 return RESULT_TYPE_BIT;
2200 return RESULT_TYPE_CHAR;
2201 return RESULT_TYPE_INT;
2204 return RESULT_TYPE_CHAR;
2205 if (IS_INT (type) && !IS_LONG (type))
2206 return RESULT_TYPE_INT;
2207 return RESULT_TYPE_OTHER;
2210 /*-----------------------------------------------------------------*/
2211 /* addCast - adds casts to a type specified by RESULT_TYPE */
2212 /*-----------------------------------------------------------------*/
2214 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2217 bool upCasted = FALSE;
2221 case RESULT_TYPE_NONE:
2222 /* if thing smaller than int must be promoted to int */
2224 getSize (tree->etype) >= INTSIZE)
2225 /* promotion not necessary or already an int */
2227 /* char and bits: promote to int */
2228 newLink = newIntLink();
2231 case RESULT_TYPE_BIT:
2233 /* already an int */
2234 bitsForType (tree->etype) >= 16 ||
2235 /* bit to bit operation: don't promote, the code generators
2236 hopefully know everything about promotion rules */
2237 bitsForType (tree->etype) == 1)
2239 newLink = newIntLink();
2242 case RESULT_TYPE_CHAR:
2243 if (IS_CHAR (tree->etype) ||
2244 IS_FLOAT(tree->etype) ||
2245 IS_FIXED(tree->etype))
2247 newLink = newCharLink();
2249 case RESULT_TYPE_INT:
2251 if (getSize (tree->etype) > INTSIZE)
2253 /* warn ("Loosing significant digits"); */
2257 /* char: promote to int */
2259 getSize (tree->etype) >= INTSIZE)
2261 newLink = newIntLink();
2264 case RESULT_TYPE_IFX:
2265 case RESULT_TYPE_OTHER:
2267 /* return type is ifx, long, float: promote char to int */
2268 getSize (tree->etype) >= INTSIZE)
2270 newLink = newIntLink();
2276 tree->decorated = 0;
2277 tree = newNode (CAST, newAst_LINK (newLink), tree);
2278 tree->lineno = tree->right->lineno;
2279 /* keep unsigned type during cast to smaller type,
2280 but not when promoting from char to int */
2282 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2283 return decorateType (tree, resultType);
2286 /*-----------------------------------------------------------------*/
2287 /* resultTypePropagate - decides if resultType can be propagated */
2288 /*-----------------------------------------------------------------*/
2290 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2292 switch (tree->opval.op)
2309 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2310 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2311 return RESULT_TYPE_NONE;
2316 return RESULT_TYPE_NONE;
2320 return RESULT_TYPE_IFX;
2322 return RESULT_TYPE_NONE;
2326 /*-----------------------------------------------------------------*/
2327 /* getLeftResultType - gets type from left branch for propagation */
2328 /*-----------------------------------------------------------------*/
2330 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2332 switch (tree->opval.op)
2336 if (IS_PTR (LTYPE (tree)))
2337 return RESULT_TYPE_NONE;
2339 return getResultTypeFromType (LETYPE (tree));
2341 if (IS_PTR (currFunc->type->next))
2342 return RESULT_TYPE_NONE;
2344 return getResultTypeFromType (currFunc->type->next);
2346 if (!IS_ARRAY (LTYPE (tree)))
2348 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2349 return RESULT_TYPE_CHAR;
2356 /*------------------------------------------------------------------*/
2357 /* gatherImplicitVariables: assigns correct type information to */
2358 /* symbols and values created by replaceAstWithTemporary */
2359 /* and adds the symbols to the declarations list of the */
2360 /* innermost block that contains them */
2361 /*------------------------------------------------------------------*/
2363 gatherImplicitVariables (ast * tree, ast * block)
2368 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2370 /* keep track of containing scope */
2373 if (tree->type == EX_OP && tree->opval.op == '=' &&
2374 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2376 symbol *assignee = tree->left->opval.val->sym;
2378 /* special case for assignment to compiler-generated temporary variable:
2379 compute type of RHS, and set the symbol's type to match */
2380 if (assignee->type == NULL && assignee->infertype) {
2381 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2383 if (dtr != tree->right)
2386 assignee->type = copyLinkChain(TTYPE(dtr));
2387 assignee->etype = getSpec(assignee->type);
2388 SPEC_SCLS (assignee->etype) = S_AUTO;
2389 SPEC_OCLS (assignee->etype) = NULL;
2390 SPEC_EXTR (assignee->etype) = 0;
2391 SPEC_STAT (assignee->etype) = 0;
2392 SPEC_VOLATILE (assignee->etype) = 0;
2393 SPEC_ABSA (assignee->etype) = 0;
2395 wassertl(block != NULL, "implicit variable not contained in block");
2396 wassert(assignee->next == NULL);
2397 if (block != NULL) {
2398 symbol **decl = &(block->values.sym);
2401 wassert(*decl != assignee); /* should not already be in list */
2402 decl = &( (*decl)->next );
2409 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2410 tree->opval.val->type == NULL &&
2411 tree->opval.val->sym &&
2412 tree->opval.val->sym->infertype)
2414 /* fixup type of value for compiler-inferred temporary var */
2415 tree->opval.val->type = tree->opval.val->sym->type;
2416 tree->opval.val->etype = tree->opval.val->sym->etype;
2419 gatherImplicitVariables(tree->left, block);
2420 gatherImplicitVariables(tree->right, block);
2423 /*--------------------------------------------------------------------*/
2424 /* decorateType - compute type for this tree, also does type checking.*/
2425 /* This is done bottom up, since type has to flow upwards. */
2426 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2427 /* result is a char and the operand(s) are int's. */
2428 /* It also does constant folding, and parameter checking. */
2429 /*--------------------------------------------------------------------*/
2431 decorateType (ast * tree, RESULT_TYPE resultType)
2435 RESULT_TYPE resultTypeProp;
2440 /* if already has type then do nothing */
2441 if (tree->decorated)
2444 tree->decorated = 1;
2447 /* print the line */
2448 /* if not block & function */
2449 if (tree->type == EX_OP &&
2450 (tree->opval.op != FUNCTION &&
2451 tree->opval.op != BLOCK &&
2452 tree->opval.op != NULLOP))
2454 filename = tree->filename;
2455 lineno = tree->lineno;
2459 /* if any child is an error | this one is an error do nothing */
2460 if (tree->isError ||
2461 (tree->left && tree->left->isError) ||
2462 (tree->right && tree->right->isError))
2465 /*------------------------------------------------------------------*/
2466 /*----------------------------*/
2467 /* leaf has been reached */
2468 /*----------------------------*/
2469 lineno = tree->lineno;
2470 /* if this is of type value */
2471 /* just get the type */
2472 if (tree->type == EX_VALUE)
2475 if (IS_LITERAL (tree->opval.val->etype))
2478 /* if this is a character array then declare it */
2479 if (IS_ARRAY (tree->opval.val->type))
2480 tree->opval.val = stringToSymbol (tree->opval.val);
2482 /* otherwise just copy the type information */
2483 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2487 if (tree->opval.val->sym)
2489 /* if the undefined flag is set then give error message */
2490 if (tree->opval.val->sym->undefined)
2492 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2494 TTYPE (tree) = TETYPE (tree) =
2495 tree->opval.val->type = tree->opval.val->sym->type =
2496 tree->opval.val->etype = tree->opval.val->sym->etype =
2497 copyLinkChain (INTTYPE);
2499 else if (tree->opval.val->sym->implicit)
2501 /* if implicit i.e. struct/union member then no type */
2502 TTYPE (tree) = TETYPE (tree) = NULL;
2506 /* copy the type from the value into the ast */
2507 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2509 /* and mark the symbol as referenced */
2510 tree->opval.val->sym->isref = 1;
2514 wassert(0); /* unreached: all values are literals or symbols */
2519 /* if type link for the case of cast */
2520 if (tree->type == EX_LINK)
2522 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2530 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2532 if (tree->left && tree->left->type == EX_OPERAND
2533 && (tree->left->opval.op == INC_OP
2534 || tree->left->opval.op == DEC_OP)
2535 && tree->left->left)
2537 tree->left->right = tree->left->left;
2538 tree->left->left = NULL;
2540 if (tree->right && tree->right->type == EX_OPERAND
2541 && (tree->right->opval.op == INC_OP
2542 || tree->right->opval.op == DEC_OP)
2543 && tree->right->left)
2545 tree->right->right = tree->right->left;
2546 tree->right->left = NULL;
2551 /* Before decorating the left branch we've to decide in dependence
2552 upon tree->opval.op, if resultType can be propagated */
2553 resultTypeProp = resultTypePropagate (tree, resultType);
2555 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2556 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2558 dtl = decorateType (tree->left, resultTypeProp);
2560 /* if an array node, we may need to swap branches */
2561 if (tree->opval.op == '[')
2563 /* determine which is the array & which the index */
2564 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2565 IS_INTEGRAL (LTYPE (tree)))
2567 ast *tempTree = tree->left;
2568 tree->left = tree->right;
2569 tree->right = tempTree;
2573 /* After decorating the left branch there's type information available
2574 in tree->left->?type. If the op is e.g. '=' we extract the type
2575 information from there and propagate it to the right branch. */
2576 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2578 switch (tree->opval.op)
2581 /* delay right side for '?' operator since conditional macro
2582 expansions might rely on this */
2586 /* decorate right side for CALL (parameter list) in processParms();
2587 there is resultType available */
2591 /* don't allocate string if it is a sizeof argument */
2593 dtr = decorateType (tree->right, resultTypeProp);
2597 dtr = decorateType (tree->right, resultTypeProp);
2601 /* this is to take care of situations
2602 when the tree gets rewritten */
2603 if (dtl != tree->left)
2605 if (dtr != tree->right)
2607 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2611 /* depending on type of operator do */
2613 switch (tree->opval.op)
2615 /*------------------------------------------------------------------*/
2616 /*----------------------------*/
2618 /*----------------------------*/
2621 /* first check if this is a array or a pointer */
2622 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2624 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2625 goto errorTreeReturn;
2628 /* check if the type of the idx */
2629 if (!IS_INTEGRAL (RTYPE (tree)))
2631 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2632 goto errorTreeReturn;
2635 /* if the left is an rvalue then error */
2638 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2639 goto errorTreeReturn;
2642 if (IS_LITERAL (RTYPE (tree)))
2644 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2645 int arraySize = DCL_ELEM (LTYPE (tree));
2646 if (arraySize && arrayIndex >= arraySize)
2648 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2653 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2654 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2657 /*------------------------------------------------------------------*/
2658 /*----------------------------*/
2660 /*----------------------------*/
2662 /* if this is not a structure */
2663 if (!IS_STRUCT (LTYPE (tree)))
2665 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2666 goto errorTreeReturn;
2668 TTYPE (tree) = structElemType (LTYPE (tree),
2669 (tree->right->type == EX_VALUE ?
2670 tree->right->opval.val : NULL));
2671 TETYPE (tree) = getSpec (TTYPE (tree));
2674 /*------------------------------------------------------------------*/
2675 /*----------------------------*/
2676 /* struct/union pointer */
2677 /*----------------------------*/
2679 /* if not pointer to a structure */
2680 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2682 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2683 goto errorTreeReturn;
2686 if (!IS_STRUCT (LTYPE (tree)->next))
2688 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2689 goto errorTreeReturn;
2692 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2693 (tree->right->type == EX_VALUE ?
2694 tree->right->opval.val : NULL));
2695 TETYPE (tree) = getSpec (TTYPE (tree));
2697 /* adjust the storage class */
2698 switch (DCL_TYPE(tree->left->ftype)) {
2700 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2703 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2706 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2709 SPEC_SCLS (TETYPE (tree)) = 0;
2712 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2715 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2718 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2721 SPEC_SCLS (TETYPE (tree)) = 0;
2728 /* This breaks with extern declarations, bitfields, and perhaps other */
2729 /* cases (gcse). Let's leave this optimization disabled for now and */
2730 /* ponder if there's a safe way to do this. -- EEP */
2732 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2733 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2735 /* If defined struct type at addr var
2736 then rewrite (&struct var)->member
2738 and define membertype at (addr+offsetof(struct var,member)) temp
2741 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2742 AST_SYMBOL(tree->right));
2744 sym = newSymbol(genSymName (0), 0);
2745 sym->type = TTYPE (tree);
2746 sym->etype = getSpec(sym->type);
2747 sym->lineDef = tree->lineno;
2750 SPEC_STAT (sym->etype) = 1;
2751 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2753 SPEC_ABSA(sym->etype) = 1;
2754 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2757 AST_VALUE (tree) = symbolVal(sym);
2760 tree->type = EX_VALUE;
2768 /*------------------------------------------------------------------*/
2769 /*----------------------------*/
2770 /* ++/-- operation */
2771 /*----------------------------*/
2775 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2776 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2777 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2778 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2787 /*------------------------------------------------------------------*/
2788 /*----------------------------*/
2790 /*----------------------------*/
2791 case '&': /* can be unary */
2792 /* if right is NULL then unary operation */
2793 if (tree->right) /* not an unary operation */
2796 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2798 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2799 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2800 printTypeChain (LTYPE (tree), stderr);
2801 fprintf (stderr, ",");
2802 printTypeChain (RTYPE (tree), stderr);
2803 fprintf (stderr, "\n");
2804 goto errorTreeReturn;
2807 /* if they are both literal */
2808 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2810 tree->type = EX_VALUE;
2811 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2812 valFromType (RETYPE (tree)), '&');
2814 tree->right = tree->left = NULL;
2815 TETYPE (tree) = tree->opval.val->etype;
2816 TTYPE (tree) = tree->opval.val->type;
2820 /* see if this is a GETHBIT operation if yes
2823 ast *otree = optimizeGetHbit (tree, resultType);
2826 return decorateType (otree, RESULT_TYPE_NONE);
2829 /* see if this is a GETABIT operation if yes
2832 ast *otree = optimizeGetAbit (tree, resultType);
2835 return decorateType (otree, RESULT_TYPE_NONE);
2838 /* see if this is a GETBYTE operation if yes
2841 ast *otree = optimizeGetByte (tree, resultType);
2844 return decorateType (otree, RESULT_TYPE_NONE);
2847 /* see if this is a GETWORD operation if yes
2850 ast *otree = optimizeGetWord (tree, resultType);
2853 return decorateType (otree, RESULT_TYPE_NONE);
2856 /* if left is a literal exchange left & right */
2857 if (IS_LITERAL (LTYPE (tree)))
2859 ast *tTree = tree->left;
2860 tree->left = tree->right;
2861 tree->right = tTree;
2864 /* if right is a literal and */
2865 /* we can find a 2nd literal in an and-tree then */
2866 /* rearrange the tree */
2867 if (IS_LITERAL (RTYPE (tree)))
2870 ast *litTree = searchLitOp (tree, &parent, "&");
2874 ast *tTree = litTree->left;
2875 litTree->left = tree->right;
2876 tree->right = tTree;
2877 /* both operands in litTree are literal now */
2878 decorateType (parent, resultType);
2882 LRVAL (tree) = RRVAL (tree) = 1;
2884 TTYPE (tree) = computeType (LTYPE (tree),
2888 TETYPE (tree) = getSpec (TTYPE (tree));
2893 /*------------------------------------------------------------------*/
2894 /*----------------------------*/
2896 /*----------------------------*/
2897 p = newLink (DECLARATOR);
2898 /* if bit field then error */
2899 if (IS_BITVAR (tree->left->etype))
2901 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2902 goto errorTreeReturn;
2905 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2907 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2908 goto errorTreeReturn;
2911 if (IS_FUNC (LTYPE (tree)))
2913 // this ought to be ignored
2914 return (tree->left);
2917 if (IS_LITERAL(LTYPE(tree)))
2919 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2920 goto errorTreeReturn;
2925 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2926 goto errorTreeReturn;
2929 DCL_TYPE (p) = POINTER;
2930 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2931 DCL_TYPE (p) = CPOINTER;
2932 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2933 DCL_TYPE (p) = FPOINTER;
2934 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2935 DCL_TYPE (p) = PPOINTER;
2936 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2937 DCL_TYPE (p) = IPOINTER;
2938 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2939 DCL_TYPE (p) = EEPPOINTER;
2940 else if (SPEC_OCLS(tree->left->etype))
2941 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2943 DCL_TYPE (p) = POINTER;
2945 if (IS_AST_SYM_VALUE (tree->left))
2947 AST_SYMBOL (tree->left)->addrtaken = 1;
2948 AST_SYMBOL (tree->left)->allocreq = 1;
2951 p->next = LTYPE (tree);
2953 TETYPE (tree) = getSpec (TTYPE (tree));
2958 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2959 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2961 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2962 AST_SYMBOL(tree->left->right));
2963 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2964 valueFromLit(element->offset));
2967 tree->type = EX_VALUE;
2968 tree->values.literalFromCast = 1;
2974 /*------------------------------------------------------------------*/
2975 /*----------------------------*/
2977 /*----------------------------*/
2979 /* if the rewrite succeeds then don't go any further */
2981 ast *wtree = optimizeRRCRLC (tree);
2983 return decorateType (wtree, RESULT_TYPE_NONE);
2985 wtree = optimizeSWAP (tree);
2987 return decorateType (wtree, RESULT_TYPE_NONE);
2990 /* if left is a literal exchange left & right */
2991 if (IS_LITERAL (LTYPE (tree)))
2993 ast *tTree = tree->left;
2994 tree->left = tree->right;
2995 tree->right = tTree;
2998 /* if right is a literal and */
2999 /* we can find a 2nd literal in an or-tree then */
3000 /* rearrange the tree */
3001 if (IS_LITERAL (RTYPE (tree)))
3004 ast *litTree = searchLitOp (tree, &parent, "|");
3008 ast *tTree = litTree->left;
3009 litTree->left = tree->right;
3010 tree->right = tTree;
3011 /* both operands in tTree are literal now */
3012 decorateType (parent, resultType);
3017 /*------------------------------------------------------------------*/
3018 /*----------------------------*/
3020 /*----------------------------*/
3022 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3024 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3025 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3026 printTypeChain (LTYPE (tree), stderr);
3027 fprintf (stderr, ",");
3028 printTypeChain (RTYPE (tree), stderr);
3029 fprintf (stderr, "\n");
3030 goto errorTreeReturn;
3033 /* if they are both literal then rewrite the tree */
3034 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3036 tree->type = EX_VALUE;
3037 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3038 valFromType (RETYPE (tree)),
3040 tree->right = tree->left = NULL;
3041 TETYPE (tree) = tree->opval.val->etype;
3042 TTYPE (tree) = tree->opval.val->type;
3046 /* if left is a literal exchange left & right */
3047 if (IS_LITERAL (LTYPE (tree)))
3049 ast *tTree = tree->left;
3050 tree->left = tree->right;
3051 tree->right = tTree;
3054 /* if right is a literal and */
3055 /* we can find a 2nd literal in a xor-tree then */
3056 /* rearrange the tree */
3057 if (IS_LITERAL (RTYPE (tree)) &&
3058 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3061 ast *litTree = searchLitOp (tree, &parent, "^");
3065 ast *tTree = litTree->left;
3066 litTree->left = tree->right;
3067 tree->right = tTree;
3068 /* both operands in litTree are literal now */
3069 decorateType (parent, resultType);
3073 LRVAL (tree) = RRVAL (tree) = 1;
3075 TTYPE (tree) = computeType (LTYPE (tree),
3079 TETYPE (tree) = getSpec (TTYPE (tree));
3083 /*------------------------------------------------------------------*/
3084 /*----------------------------*/
3086 /*----------------------------*/
3088 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3090 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3091 goto errorTreeReturn;
3093 /* if they are both literal then */
3094 /* rewrite the tree */
3095 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3097 tree->type = EX_VALUE;
3098 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3099 valFromType (RETYPE (tree)));
3100 tree->right = tree->left = NULL;
3101 TETYPE (tree) = getSpec (TTYPE (tree) =
3102 tree->opval.val->type);
3106 LRVAL (tree) = RRVAL (tree) = 1;
3108 TETYPE (tree) = getSpec (TTYPE (tree) =
3109 computeType (LTYPE (tree),
3114 /* if right is a literal and */
3115 /* left is also a division by a literal then */
3116 /* rearrange the tree */
3117 if (IS_LITERAL (RTYPE (tree))
3118 /* avoid infinite loop */
3119 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3122 ast *litTree = searchLitOp (tree, &parent, "/");
3125 if (IS_LITERAL (RTYPE (litTree)))
3129 litTree->right = newNode ('*',
3131 copyAst (tree->right));
3132 litTree->right->lineno = tree->lineno;
3134 tree->right->opval.val = constCharVal (1);
3135 decorateType (parent, resultType);
3139 /* litTree->left is literal: no gcse possible.
3140 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3141 this would cause an infinit loop. */
3142 parent->decorated = 1;
3143 decorateType (litTree, resultType);
3150 /*------------------------------------------------------------------*/
3151 /*----------------------------*/
3153 /*----------------------------*/
3155 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3157 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3158 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3159 printTypeChain (LTYPE (tree), stderr);
3160 fprintf (stderr, ",");
3161 printTypeChain (RTYPE (tree), stderr);
3162 fprintf (stderr, "\n");
3163 goto errorTreeReturn;
3165 /* if they are both literal then */
3166 /* rewrite the tree */
3167 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3169 tree->type = EX_VALUE;
3170 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3171 valFromType (RETYPE (tree)));
3172 tree->right = tree->left = NULL;
3173 TETYPE (tree) = getSpec (TTYPE (tree) =
3174 tree->opval.val->type);
3177 LRVAL (tree) = RRVAL (tree) = 1;
3178 TETYPE (tree) = getSpec (TTYPE (tree) =
3179 computeType (LTYPE (tree),
3185 /*------------------------------------------------------------------*/
3186 /*----------------------------*/
3187 /* address dereference */
3188 /*----------------------------*/
3189 case '*': /* can be unary : if right is null then unary operation */
3192 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3194 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3195 goto errorTreeReturn;
3200 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3201 goto errorTreeReturn;
3203 if (IS_ADDRESS_OF_OP(tree->left))
3205 /* replace *&obj with obj */
3206 return tree->left->left;
3208 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3209 TETYPE (tree) = getSpec (TTYPE (tree));
3210 /* adjust the storage class */
3211 switch (DCL_TYPE(tree->left->ftype)) {
3213 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3216 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3219 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3222 SPEC_SCLS (TETYPE (tree)) = 0;
3225 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3228 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3231 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3234 SPEC_SCLS (TETYPE (tree)) = 0;
3243 /*------------------------------------------------------------------*/
3244 /*----------------------------*/
3245 /* multiplication */
3246 /*----------------------------*/
3247 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3249 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3250 goto errorTreeReturn;
3253 /* if they are both literal then */
3254 /* rewrite the tree */
3255 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3257 tree->type = EX_VALUE;
3258 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3259 valFromType (RETYPE (tree)));
3260 tree->right = tree->left = NULL;
3261 TETYPE (tree) = getSpec (TTYPE (tree) =
3262 tree->opval.val->type);
3266 /* if left is a literal exchange left & right */
3267 if (IS_LITERAL (LTYPE (tree)))
3269 ast *tTree = tree->left;
3270 tree->left = tree->right;
3271 tree->right = tTree;
3274 /* if right is a literal and */
3275 /* we can find a 2nd literal in a mul-tree then */
3276 /* rearrange the tree */
3277 if (IS_LITERAL (RTYPE (tree)))
3280 ast *litTree = searchLitOp (tree, &parent, "*");
3284 ast *tTree = litTree->left;
3285 litTree->left = tree->right;
3286 tree->right = tTree;
3287 /* both operands in litTree are literal now */
3288 decorateType (parent, resultType);
3292 LRVAL (tree) = RRVAL (tree) = 1;
3293 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3294 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3295 TETYPE (tree) = getSpec (TTYPE (tree) =
3296 computeType (LTYPE (tree),
3303 /*------------------------------------------------------------------*/
3304 /*----------------------------*/
3305 /* unary '+' operator */
3306 /*----------------------------*/
3311 if (!IS_ARITHMETIC (LTYPE (tree)))
3313 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3314 goto errorTreeReturn;
3317 /* if left is a literal then do it */
3318 if (IS_LITERAL (LTYPE (tree)))
3320 tree->type = EX_VALUE;
3321 tree->opval.val = valFromType (LETYPE (tree));
3323 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3327 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3331 /*------------------------------------------------------------------*/
3332 /*----------------------------*/
3334 /*----------------------------*/
3336 /* this is not a unary operation */
3337 /* if both pointers then problem */
3338 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3339 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3341 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3342 goto errorTreeReturn;
3345 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3346 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3348 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3349 goto errorTreeReturn;
3352 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3353 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3355 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3356 goto errorTreeReturn;
3358 /* if they are both literal then */
3359 /* rewrite the tree */
3360 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3362 tree->type = EX_VALUE;
3363 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3364 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3365 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3366 valFromType (RETYPE (tree)));
3367 tree->right = tree->left = NULL;
3368 TETYPE (tree) = getSpec (TTYPE (tree) =
3369 tree->opval.val->type);
3373 /* if the right is a pointer or left is a literal
3374 xchange left & right */
3375 if (IS_ARRAY (RTYPE (tree)) ||
3376 IS_PTR (RTYPE (tree)) ||
3377 IS_LITERAL (LTYPE (tree)))
3379 ast *tTree = tree->left;
3380 tree->left = tree->right;
3381 tree->right = tTree;
3384 /* if right is a literal and */
3385 /* left is also an addition/subtraction with a literal then */
3386 /* rearrange the tree */
3387 if (IS_LITERAL (RTYPE (tree)))
3389 ast *litTree, *parent;
3390 litTree = searchLitOp (tree, &parent, "+-");
3393 if (litTree->opval.op == '+')
3397 ast *tTree = litTree->left;
3398 litTree->left = tree->right;
3399 tree->right = tree->left;
3402 else if (litTree->opval.op == '-')
3404 if (IS_LITERAL (RTYPE (litTree)))
3408 ast *tTree = litTree->left;
3409 litTree->left = tree->right;
3410 tree->right = tTree;
3416 ast *tTree = litTree->right;
3417 litTree->right = tree->right;
3418 tree->right = tTree;
3419 litTree->opval.op = '+';
3420 tree->opval.op = '-';
3423 decorateType (parent, resultType);
3427 LRVAL (tree) = RRVAL (tree) = 1;
3428 /* if the left is a pointer */
3429 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3430 TETYPE (tree) = getSpec (TTYPE (tree) =
3434 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3435 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3436 TETYPE (tree) = getSpec (TTYPE (tree) =
3437 computeType (LTYPE (tree),
3445 /*------------------------------------------------------------------*/
3446 /*----------------------------*/
3448 /*----------------------------*/
3449 case '-': /* can be unary */
3450 /* if right is null then unary */
3454 if (!IS_ARITHMETIC (LTYPE (tree)))
3456 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3457 goto errorTreeReturn;
3460 /* if left is a literal then do it */
3461 if (IS_LITERAL (LTYPE (tree)))
3463 tree->type = EX_VALUE;
3464 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3466 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3469 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3470 TETYPE (tree) = getSpec (TTYPE (tree) =
3471 computeType (LTYPE (tree),
3479 /*------------------------------------------------------------------*/
3480 /*----------------------------*/
3482 /*----------------------------*/
3484 if (!(IS_PTR (LTYPE (tree)) ||
3485 IS_ARRAY (LTYPE (tree)) ||
3486 IS_ARITHMETIC (LTYPE (tree))))
3488 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3489 goto errorTreeReturn;
3492 if (!(IS_PTR (RTYPE (tree)) ||
3493 IS_ARRAY (RTYPE (tree)) ||
3494 IS_ARITHMETIC (RTYPE (tree))))
3496 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3497 goto errorTreeReturn;
3500 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3501 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3502 IS_INTEGRAL (RTYPE (tree))))
3504 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3505 goto errorTreeReturn;
3508 /* if they are both literal then */
3509 /* rewrite the tree */
3510 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3512 tree->type = EX_VALUE;
3513 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3514 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3515 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3516 valFromType (RETYPE (tree)));
3517 tree->right = tree->left = NULL;
3518 TETYPE (tree) = getSpec (TTYPE (tree) =
3519 tree->opval.val->type);
3523 /* if the left & right are equal then zero */
3524 if (isAstEqual (tree->left, tree->right))
3526 tree->type = EX_VALUE;
3527 tree->left = tree->right = NULL;
3528 tree->opval.val = constCharVal (0);
3529 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3533 /* if both of them are pointers or arrays then */
3534 /* the result is going to be an integer */
3535 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3536 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3537 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3539 /* if only the left is a pointer */
3540 /* then result is a pointer */
3541 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3542 TETYPE (tree) = getSpec (TTYPE (tree) =
3546 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3547 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3549 TETYPE (tree) = getSpec (TTYPE (tree) =
3550 computeType (LTYPE (tree),
3556 LRVAL (tree) = RRVAL (tree) = 1;
3558 /* if right is a literal and */
3559 /* left is also an addition/subtraction with a literal then */
3560 /* rearrange the tree */
3561 if (IS_LITERAL (RTYPE (tree))
3562 /* avoid infinite loop */
3563 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3565 ast *litTree, *litParent;
3566 litTree = searchLitOp (tree, &litParent, "+-");
3569 if (litTree->opval.op == '+')
3573 ast *tTree = litTree->left;
3574 litTree->left = litTree->right;
3575 litTree->right = tree->right;
3576 tree->right = tTree;
3577 tree->opval.op = '+';
3578 litTree->opval.op = '-';
3580 else if (litTree->opval.op == '-')
3582 if (IS_LITERAL (RTYPE (litTree)))
3586 ast *tTree = litTree->left;
3587 litTree->left = tree->right;
3588 tree->right = litParent->left;
3589 litParent->left = tTree;
3590 litTree->opval.op = '+';
3592 tree->decorated = 0;
3593 decorateType (tree, resultType);
3599 ast *tTree = litTree->right;
3600 litTree->right = tree->right;
3601 tree->right = tTree;
3604 decorateType (litParent, resultType);
3609 /*------------------------------------------------------------------*/
3610 /*----------------------------*/
3612 /*----------------------------*/
3614 /* can be only integral type */
3615 if (!IS_INTEGRAL (LTYPE (tree)))
3617 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3618 goto errorTreeReturn;
3621 /* if left is a literal then do it */
3622 if (IS_LITERAL (LTYPE (tree)))
3624 tree->type = EX_VALUE;
3625 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3627 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3628 return addCast (tree, resultTypeProp, TRUE);
3631 if (resultType == RESULT_TYPE_BIT &&
3632 IS_UNSIGNED (tree->left->etype) &&
3633 getSize (tree->left->etype) < INTSIZE)
3635 /* promotion rules are responsible for this strange result:
3636 bit -> int -> ~int -> bit
3637 uchar -> int -> ~int -> bit
3639 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3641 /* optimize bit-result, even if we optimize a buggy source */
3642 tree->type = EX_VALUE;
3643 tree->opval.val = constCharVal (1);
3646 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3648 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3651 /*------------------------------------------------------------------*/
3652 /*----------------------------*/
3654 /*----------------------------*/
3656 /* can be pointer */
3657 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3658 !IS_PTR (LTYPE (tree)) &&
3659 !IS_ARRAY (LTYPE (tree)))
3661 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3662 goto errorTreeReturn;
3665 /* if left is another '!' */
3666 if (IS_AST_NOT_OPER (tree->left))
3668 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3670 /* replace double '!!X' by 'X' */
3671 return tree->left->left;
3673 /* remove double '!!X' by 'X ? 1 : 0' */
3674 tree->opval.op = '?';
3675 tree->left = tree->left->left;
3676 tree->right = newNode (':',
3677 newAst_VALUE (constCharVal (1)),
3678 newAst_VALUE (constCharVal (0)));
3679 tree->right->lineno = tree->lineno;
3680 tree->decorated = 0;
3681 return decorateType (tree, resultType);
3684 /* if left is a literal then do it */
3685 if (IS_LITERAL (LTYPE (tree)))
3687 tree->type = EX_VALUE;
3688 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3690 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3694 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3697 /*------------------------------------------------------------------*/
3698 /*----------------------------*/
3700 /*----------------------------*/
3704 TTYPE (tree) = LTYPE (tree);
3705 TETYPE (tree) = LETYPE (tree);
3710 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3714 TTYPE (tree) = TETYPE (tree) = newCharLink();
3718 TTYPE (tree) = TETYPE (tree) = newIntLink();
3723 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3725 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3726 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3727 printTypeChain (LTYPE (tree), stderr);
3728 fprintf (stderr, ",");
3729 printTypeChain (RTYPE (tree), stderr);
3730 fprintf (stderr, "\n");
3731 goto errorTreeReturn;
3734 /* make smaller type only if it's a LEFT_OP */
3735 if (tree->opval.op == LEFT_OP)
3736 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3738 /* if they are both literal then */
3739 /* rewrite the tree */
3740 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3742 tree->type = EX_VALUE;
3743 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3744 valFromType (RETYPE (tree)),
3745 (tree->opval.op == LEFT_OP ? 1 : 0));
3746 tree->right = tree->left = NULL;
3747 TETYPE (tree) = getSpec (TTYPE (tree) =
3748 tree->opval.val->type);
3752 /* see if this is a GETBYTE operation if yes
3755 ast *otree = optimizeGetByte (tree, resultType);
3758 return decorateType (otree, RESULT_TYPE_NONE);
3761 /* see if this is a GETWORD operation if yes
3764 ast *otree = optimizeGetWord (tree, resultType);
3767 return decorateType (otree, RESULT_TYPE_NONE);
3770 LRVAL (tree) = RRVAL (tree) = 1;
3771 if (tree->opval.op == LEFT_OP)
3773 TETYPE (tree) = getSpec (TTYPE (tree) =
3774 computeType (LTYPE (tree),
3781 /* no promotion necessary */
3782 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3783 if (IS_LITERAL (TTYPE (tree)))
3784 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3787 /* if only the right side is a literal & we are
3788 shifting more than size of the left operand then zero */
3789 if (IS_LITERAL (RTYPE (tree)) &&
3790 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3791 (getSize (TETYPE (tree)) * 8))
3793 if (tree->opval.op==LEFT_OP ||
3794 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3796 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3797 (tree->opval.op == LEFT_OP ? "left" : "right"));
3798 tree->type = EX_VALUE;
3799 tree->left = tree->right = NULL;
3800 tree->opval.val = constCharVal (0);
3801 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3808 /*------------------------------------------------------------------*/
3809 /*----------------------------*/
3811 /*----------------------------*/
3812 case CAST: /* change the type */
3813 /* cannot cast to an aggregate type */
3814 if (IS_AGGREGATE (LTYPE (tree)))
3816 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3817 goto errorTreeReturn;
3820 /* make sure the type is complete and sane */
3821 changePointer(LTYPE(tree));
3822 checkTypeSanity(LETYPE(tree), "(cast)");
3824 /* if 'from' and 'to' are the same remove the superfluous cast, */
3825 /* this helps other optimizations */
3826 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3831 /* If code memory is read only, then pointers to code memory */
3832 /* implicitly point to constants -- make this explicit */
3834 sym_link *t = LTYPE(tree);
3835 while (t && t->next)
3837 if (IS_CODEPTR(t) && port->mem.code_ro)
3839 if (IS_SPEC(t->next))
3840 SPEC_CONST (t->next) = 1;
3842 DCL_PTR_CONST (t->next) = 1;
3849 /* if the right is a literal replace the tree */
3850 if (IS_LITERAL (RETYPE (tree))) {
3851 if (!IS_PTR (LTYPE (tree))) {
3852 tree->type = EX_VALUE;
3854 valCastLiteral (LTYPE (tree),
3855 floatFromVal (valFromType (RETYPE (tree))));
3858 TTYPE (tree) = tree->opval.val->type;
3859 tree->values.literalFromCast = 1;
3860 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3861 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3862 sym_link *rest = LTYPE(tree)->next;
3863 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3864 TTYPE(tree) = newLink(DECLARATOR);
3865 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3866 TTYPE(tree)->next = rest;
3867 tree->left->opval.lnk = TTYPE(tree);
3870 TTYPE (tree) = LTYPE (tree);
3874 TTYPE (tree) = LTYPE (tree);
3878 #if 0 // this is already checked, now this could be explicit
3879 /* if pointer to struct then check names */
3880 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3881 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3882 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3884 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3885 SPEC_STRUCT(LETYPE(tree))->tag);
3888 if (IS_ADDRESS_OF_OP(tree->right)
3889 && IS_AST_SYM_VALUE (tree->right->left)
3890 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3892 symbol * sym = AST_SYMBOL (tree->right->left);
3893 unsigned int gptype = 0;
3894 unsigned int addr = SPEC_ADDR (sym->etype);
3896 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3897 || TARGET_IS_PIC16) )
3899 switch (SPEC_SCLS (sym->etype))
3902 gptype = GPTYPE_CODE;
3905 gptype = GPTYPE_FAR;
3909 gptype = GPTYPE_NEAR;
3912 gptype = GPTYPE_XSTACK;
3917 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3918 gptype = GPTYPE_NEAR;
3920 addr |= gptype << (8*(GPTRSIZE - 1));
3923 tree->type = EX_VALUE;
3925 valCastLiteral (LTYPE (tree), addr);
3926 TTYPE (tree) = tree->opval.val->type;
3927 TETYPE (tree) = getSpec (TTYPE (tree));
3930 tree->values.literalFromCast = 1;
3934 /* handle offsetof macro: */
3935 /* #define offsetof(TYPE, MEMBER) \ */
3936 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3937 if (IS_ADDRESS_OF_OP(tree->right)
3938 && IS_AST_OP (tree->right->left)
3939 && tree->right->left->opval.op == PTR_OP
3940 && IS_AST_OP (tree->right->left->left)
3941 && tree->right->left->left->opval.op == CAST
3942 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3944 symbol *element = getStructElement (
3945 SPEC_STRUCT (LETYPE(tree->right->left)),
3946 AST_SYMBOL(tree->right->left->right)
3950 tree->type = EX_VALUE;
3951 tree->opval.val = valCastLiteral (
3954 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3957 TTYPE (tree) = tree->opval.val->type;
3958 TETYPE (tree) = getSpec (TTYPE (tree));
3965 /* if the right is a literal replace the tree */
3966 if (IS_LITERAL (RETYPE (tree))) {
3968 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3969 /* rewrite (type *)litaddr
3971 and define type at litaddr temp
3972 (but only if type's storage class is not generic)
3974 ast *newTree = newNode ('&', NULL, NULL);
3977 TTYPE (newTree) = LTYPE (tree);
3978 TETYPE (newTree) = getSpec(LTYPE (tree));
3980 /* define a global symbol at the casted address*/
3981 sym = newSymbol(genSymName (0), 0);
3982 sym->type = LTYPE (tree)->next;
3984 sym->type = newLink (V_VOID);
3985 sym->etype = getSpec(sym->type);
3986 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3987 sym->lineDef = tree->lineno;
3990 SPEC_STAT (sym->etype) = 1;
3991 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3992 SPEC_ABSA(sym->etype) = 1;
3993 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3996 newTree->left = newAst_VALUE(symbolVal(sym));
3997 newTree->left->lineno = tree->lineno;
3998 LTYPE (newTree) = sym->type;
3999 LETYPE (newTree) = sym->etype;
4000 LLVAL (newTree) = 1;
4001 LRVAL (newTree) = 0;
4002 TLVAL (newTree) = 1;
4006 if (!IS_PTR (LTYPE (tree))) {
4007 tree->type = EX_VALUE;
4009 valCastLiteral (LTYPE (tree),
4010 floatFromVal (valFromType (RTYPE (tree))));
4011 TTYPE (tree) = tree->opval.val->type;
4014 tree->values.literalFromCast = 1;
4015 TETYPE (tree) = getSpec (TTYPE (tree));
4019 TTYPE (tree) = LTYPE (tree);
4023 TETYPE (tree) = getSpec (TTYPE (tree));
4027 /*------------------------------------------------------------------*/
4028 /*----------------------------*/
4029 /* logical &&, || */
4030 /*----------------------------*/
4033 /* each must be arithmetic type or be a pointer */
4034 if (!IS_PTR (LTYPE (tree)) &&
4035 !IS_ARRAY (LTYPE (tree)) &&
4036 !IS_INTEGRAL (LTYPE (tree)))
4038 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4039 goto errorTreeReturn;
4042 if (!IS_PTR (RTYPE (tree)) &&
4043 !IS_ARRAY (RTYPE (tree)) &&
4044 !IS_INTEGRAL (RTYPE (tree)))
4046 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4047 goto errorTreeReturn;
4049 /* if they are both literal then */
4050 /* rewrite the tree */
4051 if (IS_LITERAL (RTYPE (tree)) &&
4052 IS_LITERAL (LTYPE (tree)))
4054 tree->type = EX_VALUE;
4055 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4056 valFromType (RTYPE (tree)),
4058 tree->right = tree->left = NULL;
4059 TETYPE (tree) = getSpec (TTYPE (tree) =
4060 tree->opval.val->type);
4063 LRVAL (tree) = RRVAL (tree) = 1;
4064 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4067 /*------------------------------------------------------------------*/
4068 /*----------------------------*/
4069 /* comparison operators */
4070 /*----------------------------*/
4078 ast *lt = optimizeCompare (tree);
4084 /* if they are pointers they must be castable */
4085 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4087 if (tree->opval.op==EQ_OP &&
4088 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4089 // we cannot cast a gptr to a !gptr: switch the leaves
4090 struct ast *s=tree->left;
4091 tree->left=tree->right;
4094 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4096 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4097 fprintf (stderr, "comparing type ");
4098 printTypeChain (LTYPE (tree), stderr);
4099 fprintf (stderr, "to type ");
4100 printTypeChain (RTYPE (tree), stderr);
4101 fprintf (stderr, "\n");
4102 goto errorTreeReturn;
4105 /* else they should be promotable to one another */
4108 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4109 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4111 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4113 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4114 fprintf (stderr, "comparing type ");
4115 printTypeChain (LTYPE (tree), stderr);
4116 fprintf (stderr, "to type ");
4117 printTypeChain (RTYPE (tree), stderr);
4118 fprintf (stderr, "\n");
4119 goto errorTreeReturn;
4124 CCR_RESULT ccr_result = CCR_OK;
4126 /* if left is integral and right is literal
4127 then check constant range */
4128 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4129 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4130 tree->opval.op, FALSE);
4131 if (ccr_result == CCR_OK &&
4132 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4133 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4134 tree->opval.op, TRUE);
4137 case CCR_ALWAYS_TRUE:
4138 case CCR_ALWAYS_FALSE:
4139 if (!options.lessPedantic)
4140 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4141 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4142 return decorateType (newAst_VALUE (constCharVal (
4143 ccr_result == CCR_ALWAYS_TRUE ? 1 : 0)),
4151 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4152 if (tree->opval.op == '>' &&
4153 SPEC_USIGN(LETYPE(tree)) &&
4154 IS_LITERAL(RTYPE(tree)) &&
4155 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4157 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4159 /* the parent is an ifx: */
4160 /* if (unsigned value) */
4164 /* (unsigned value) ? 1 : 0 */
4165 tree->opval.op = '?';
4166 tree->right = newNode (':',
4167 newAst_VALUE (constCharVal (1)),
4168 tree->right); /* val 0 */
4169 tree->right->lineno = tree->lineno;
4170 tree->right->left->lineno = tree->lineno;
4171 tree->decorated = 0;
4172 return decorateType (tree, resultType);
4175 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4176 if (IS_LITERAL(RTYPE(tree)) &&
4177 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4178 tree->opval.op == EQ_OP &&
4179 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4181 tree->opval.op = '!';
4183 tree->decorated = 0;
4184 return decorateType (tree, resultType);
4187 /* if they are both literal then */
4188 /* rewrite the tree */
4189 if (IS_LITERAL (RTYPE (tree)) &&
4190 IS_LITERAL (LTYPE (tree)))
4192 tree->type = EX_VALUE;
4193 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4194 valFromType (RETYPE (tree)),
4196 tree->right = tree->left = NULL;
4197 TETYPE (tree) = getSpec (TTYPE (tree) =
4198 tree->opval.val->type);
4202 /* if one is 'signed char ' and the other one is 'unsigned char' */
4203 /* it's necessary to promote to int */
4204 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4205 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4207 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4208 if it's possible to use a 'signed char' */
4210 /* is left a 'unsigned char'? */
4211 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4212 /* the value range of a 'unsigned char' is 0...255;
4213 if the actual value is < 128 it can be changed to signed */
4214 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4216 /* now we've got 2 'signed char'! */
4217 SPEC_USIGN (RETYPE (tree)) = 0;
4219 /* same test for the left operand: */
4220 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4221 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4223 SPEC_USIGN (LETYPE (tree)) = 0;
4227 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4228 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4229 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4233 LRVAL (tree) = RRVAL (tree) = 1;
4234 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4236 /* condition transformations */
4238 unsigned transformedOp = 0;
4240 switch (tree->opval.op)
4242 case '<': /* transform (a < b) to !(a >= b) */
4244 transformedOp = GE_OP;
4246 case '>': /* transform (a > b) to !(a <= b) */
4248 transformedOp = LE_OP;
4250 case LE_OP: /* transform (a <= b) to !(a > b) */
4252 transformedOp = '>';
4254 case GE_OP: /* transform (a >= b) to !(a < b) */
4256 transformedOp = '<';
4258 case NE_OP: /* transform (a != b) to !(a == b) */
4260 transformedOp = EQ_OP;
4262 case EQ_OP: /* transform (a == b) to !(a != b) */
4264 transformedOp = NE_OP;
4271 tree->opval.op = transformedOp;
4272 tree->decorated = 0;
4273 tree = newNode ('!', tree, NULL);
4274 tree->lineno = tree->left->lineno;
4275 return decorateType (tree, resultType);
4281 /*------------------------------------------------------------------*/
4282 /*----------------------------*/
4284 /*----------------------------*/
4285 case SIZEOF: /* evaluate wihout code generation */
4286 /* change the type to a integer */
4288 int size = getSize (tree->right->ftype);
4290 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4291 if (!size && !IS_VOID(tree->right->ftype))
4292 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4294 tree->type = EX_VALUE;
4295 tree->opval.val = constVal (buffer);
4296 tree->right = tree->left = NULL;
4297 TETYPE (tree) = getSpec (TTYPE (tree) =
4298 tree->opval.val->type);
4302 /*------------------------------------------------------------------*/
4303 /*----------------------------*/
4305 /*----------------------------*/
4307 /* return typeof enum value */
4308 tree->type = EX_VALUE;
4311 if (IS_SPEC(tree->right->ftype)) {
4312 switch (SPEC_NOUN(tree->right->ftype)) {
4314 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4315 else typeofv = TYPEOF_INT;
4318 typeofv = TYPEOF_FLOAT;
4321 typeofv = TYPEOF_FIXED16X16;
4324 typeofv = TYPEOF_CHAR;
4327 typeofv = TYPEOF_VOID;
4330 typeofv = TYPEOF_STRUCT;
4333 typeofv = TYPEOF_BITFIELD;
4336 typeofv = TYPEOF_BIT;
4339 typeofv = TYPEOF_SBIT;
4345 switch (DCL_TYPE(tree->right->ftype)) {
4347 typeofv = TYPEOF_POINTER;
4350 typeofv = TYPEOF_FPOINTER;
4353 typeofv = TYPEOF_CPOINTER;
4356 typeofv = TYPEOF_GPOINTER;
4359 typeofv = TYPEOF_PPOINTER;
4362 typeofv = TYPEOF_IPOINTER;
4365 typeofv = TYPEOF_ARRAY;
4368 typeofv = TYPEOF_FUNCTION;
4374 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4375 tree->opval.val = constVal (buffer);
4376 tree->right = tree->left = NULL;
4377 TETYPE (tree) = getSpec (TTYPE (tree) =
4378 tree->opval.val->type);
4381 /*------------------------------------------------------------------*/
4382 /*----------------------------*/
4383 /* conditional operator '?' */
4384 /*----------------------------*/
4386 /* the type is value of the colon operator (on the right) */
4387 assert (IS_COLON_OP (tree->right));
4389 /* If already known then replace the tree : optimizer will do it
4390 but faster to do it here. If done before decorating tree->right
4391 this can save generating unused const strings. */
4392 if (IS_LITERAL (LTYPE (tree)))
4394 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4395 return decorateType (tree->right->left, resultTypeProp);
4397 return decorateType (tree->right->right, resultTypeProp);
4400 tree->right = decorateType (tree->right, resultTypeProp);
4402 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4403 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4405 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4406 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4408 if ((valTrue != 0) && (valFalse == 0))
4410 /* assign cond to result */
4411 tree->left->decorated = 0;
4412 return decorateType (tree->left, resultTypeProp);
4414 else if ((valTrue == 0) && (valFalse != 0))
4416 /* assign !cond to result */
4417 tree->opval.op = '!';
4418 tree->decorated = 0;
4420 return decorateType (tree, resultTypeProp);
4424 /* they have the same boolean value, make them equal */
4425 tree->right->left = tree->right->right;
4429 /* if they are equal then replace the tree */
4430 if (isAstEqual (tree->right->left, tree->right->right))
4432 return tree->right->left;
4435 TTYPE (tree) = RTYPE (tree);
4436 TETYPE (tree) = getSpec (TTYPE (tree));
4440 /* if they don't match we have a problem */
4441 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4442 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4444 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4445 goto errorTreeReturn;
4448 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4449 resultType, tree->opval.op);
4450 TETYPE (tree) = getSpec (TTYPE (tree));
4454 #if 0 // assignment operators are converted by the parser
4455 /*------------------------------------------------------------------*/
4456 /*----------------------------*/
4457 /* assignment operators */
4458 /*----------------------------*/
4461 /* for these it must be both must be integral */
4462 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4463 !IS_ARITHMETIC (RTYPE (tree)))
4465 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4466 goto errorTreeReturn;
4469 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4471 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4472 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4476 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4477 goto errorTreeReturn;
4488 /* for these it must be both must be integral */
4489 if (!IS_INTEGRAL (LTYPE (tree)) ||
4490 !IS_INTEGRAL (RTYPE (tree)))
4492 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4493 goto errorTreeReturn;
4496 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4498 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4499 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4503 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4504 goto errorTreeReturn;
4510 /*------------------------------------------------------------------*/
4511 /*----------------------------*/
4513 /*----------------------------*/
4515 if (!(IS_PTR (LTYPE (tree)) ||
4516 IS_ARITHMETIC (LTYPE (tree))))
4518 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4519 goto errorTreeReturn;
4522 if (!(IS_PTR (RTYPE (tree)) ||
4523 IS_ARITHMETIC (RTYPE (tree))))
4525 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4526 goto errorTreeReturn;
4529 TETYPE (tree) = getSpec (TTYPE (tree) =
4530 computeType (LTYPE (tree),
4535 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4536 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4540 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4541 goto errorTreeReturn;
4547 /*------------------------------------------------------------------*/
4548 /*----------------------------*/
4550 /*----------------------------*/
4552 /* this is not a unary operation */
4553 /* if both pointers then problem */
4554 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4556 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4557 goto errorTreeReturn;
4560 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4562 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4563 goto errorTreeReturn;
4566 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4568 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4569 goto errorTreeReturn;
4572 TETYPE (tree) = getSpec (TTYPE (tree) =
4573 computeType (LTYPE (tree),
4578 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4579 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4583 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4584 goto errorTreeReturn;
4587 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4588 tree->opval.op = '=';
4593 /*------------------------------------------------------------------*/
4594 /*----------------------------*/
4595 /* straight assignemnt */
4596 /*----------------------------*/
4598 /* cannot be an aggregate */
4599 if (IS_AGGREGATE (LTYPE (tree)))
4601 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4602 goto errorTreeReturn;
4605 /* they should either match or be castable */
4606 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4608 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4609 printFromToType(RTYPE(tree),LTYPE(tree));
4612 /* if the left side of the tree is of type void
4613 then report error */
4614 if (IS_VOID (LTYPE (tree)))
4616 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4617 printFromToType(RTYPE(tree), LTYPE(tree));
4620 TETYPE (tree) = getSpec (TTYPE (tree) =
4624 if (!tree->initMode ) {
4625 if (IS_CONSTANT(LTYPE(tree)))
4626 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4630 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4631 goto errorTreeReturn;
4636 /*------------------------------------------------------------------*/
4637 /*----------------------------*/
4638 /* comma operator */
4639 /*----------------------------*/
4641 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4644 /*------------------------------------------------------------------*/
4645 /*----------------------------*/
4647 /*----------------------------*/
4650 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4651 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4653 if (tree->left->opval.op == '*' && !tree->left->right)
4654 tree->left = tree->left->left;
4657 /* require a function or pointer to function */
4658 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4660 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4661 goto errorTreeReturn;
4664 /* if there are parms, make sure that
4665 parms are decorate / process / reverse only once */
4667 !tree->right->decorated)
4672 if (IS_FUNCPTR (LTYPE (tree)))
4674 functype = LTYPE (tree)->next;
4675 processFuncPtrArgs (functype);
4678 functype = LTYPE (tree);
4680 if (processParms (tree->left, FUNC_ARGS(functype),
4681 &tree->right, &parmNumber, TRUE))
4683 goto errorTreeReturn;
4686 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4687 !IFFUNC_ISBUILTIN(functype))
4689 reverseParms (tree->right);
4692 TTYPE (tree) = functype->next;
4693 TETYPE (tree) = getSpec (TTYPE (tree));
4697 /*------------------------------------------------------------------*/
4698 /*----------------------------*/
4699 /* return statement */
4700 /*----------------------------*/
4705 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4707 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4708 printFromToType (RTYPE(tree), currFunc->type->next);
4709 goto errorTreeReturn;
4712 if (IS_VOID (currFunc->type->next)
4714 !IS_VOID (RTYPE (tree)))
4716 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4717 goto errorTreeReturn;
4720 /* if there is going to be a casting required then add it */
4721 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4724 decorateType (newNode (CAST,
4725 newAst_LINK (copyLinkChain (currFunc->type->next)),
4735 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4737 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4738 goto errorTreeReturn;
4741 TTYPE (tree) = TETYPE (tree) = NULL;
4744 /*------------------------------------------------------------------*/
4745 /*----------------------------*/
4746 /* switch statement */
4747 /*----------------------------*/
4749 /* the switch value must be an integer */
4750 if (!IS_INTEGRAL (LTYPE (tree)))
4752 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4753 goto errorTreeReturn;
4756 TTYPE (tree) = TETYPE (tree) = NULL;
4759 /*------------------------------------------------------------------*/
4760 /*----------------------------*/
4762 /*----------------------------*/
4764 tree->left = backPatchLabels (tree->left,
4767 TTYPE (tree) = TETYPE (tree) = NULL;
4770 /*------------------------------------------------------------------*/
4771 /*----------------------------*/
4773 /*----------------------------*/
4776 AST_FOR (tree, initExpr) = decorateType (
4777 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4778 AST_FOR (tree, condExpr) = decorateType (
4779 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4780 AST_FOR (tree, loopExpr) = decorateType (
4781 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4783 /* if the for loop is reversible then
4784 reverse it otherwise do what we normally
4790 if (isLoopReversible (tree, &sym, &init, &end))
4791 return reverseLoop (tree, sym, init, end);
4793 return decorateType (createFor (AST_FOR (tree, trueLabel),
4794 AST_FOR (tree, continueLabel),
4795 AST_FOR (tree, falseLabel),
4796 AST_FOR (tree, condLabel),
4797 AST_FOR (tree, initExpr),
4798 AST_FOR (tree, condExpr),
4799 AST_FOR (tree, loopExpr),
4800 tree->left), RESULT_TYPE_NONE);
4803 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4804 "node PARAM shouldn't be processed here");
4805 /* but in processParams() */
4808 TTYPE (tree) = TETYPE (tree) = NULL;
4812 /* some error found this tree will be killed */
4814 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4815 tree->opval.op = NULLOP;
4821 /*-----------------------------------------------------------------*/
4822 /* sizeofOp - processes size of operation */
4823 /*-----------------------------------------------------------------*/
4825 sizeofOp (sym_link * type)
4830 /* make sure the type is complete and sane */
4831 checkTypeSanity(type, "(sizeof)");
4833 /* get the size and convert it to character */
4834 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4835 if (!size && !IS_VOID(type))
4836 werror (E_SIZEOF_INCOMPLETE_TYPE);
4838 /* now convert into value */
4839 return constVal (buff);
4843 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4844 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4845 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4846 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4847 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4848 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4849 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4851 /*-----------------------------------------------------------------*/
4852 /* backPatchLabels - change and or not operators to flow control */
4853 /*-----------------------------------------------------------------*/
4855 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4861 /* while-loops insert a label between the IFX and the condition,
4862 therefore look behind the label too */
4863 if (tree->opval.op == LABEL &&
4865 IS_ANDORNOT (tree->right))
4867 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4871 if (!(IS_ANDORNOT (tree)))
4874 /* if this an and */
4877 static int localLbl = 0;
4880 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4881 localLabel = newSymbol (buffer, NestLevel);
4883 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4885 /* if left is already a IFX then just change the if true label in that */
4886 if (!IS_IFX (tree->left))
4887 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4889 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4890 /* right is a IFX then just join */
4891 if (IS_IFX (tree->right))
4892 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4894 tree->right = createLabel (localLabel, tree->right);
4895 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4897 return newNode (NULLOP, tree->left, tree->right);
4900 /* if this is an or operation */
4903 static int localLbl = 0;
4906 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4907 localLabel = newSymbol (buffer, NestLevel);
4909 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4911 /* if left is already a IFX then just change the if true label in that */
4912 if (!IS_IFX (tree->left))
4913 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4915 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4916 /* right is a IFX then just join */
4917 if (IS_IFX (tree->right))
4918 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4920 tree->right = createLabel (localLabel, tree->right);
4921 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4923 return newNode (NULLOP, tree->left, tree->right);
4929 /* call with exchanged labels */
4930 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4932 /* if left isn't already a IFX */
4933 if (!IS_IFX (tree->left))
4935 tree->left = newNode (IFX, tree->left, NULL);
4936 tree->left->trueLabel = falseLabel;
4937 tree->left->falseLabel = trueLabel;
4944 tree->trueLabel = trueLabel;
4945 tree->falseLabel = falseLabel;
4952 /*-----------------------------------------------------------------*/
4953 /* createBlock - create expression tree for block */
4954 /*-----------------------------------------------------------------*/
4956 createBlock (symbol * decl, ast * body)
4960 /* if the block has nothing */
4964 ex = newNode (BLOCK, NULL, body);
4965 ex->values.sym = decl;
4972 /*-----------------------------------------------------------------*/
4973 /* createLabel - creates the expression tree for labels */
4974 /*-----------------------------------------------------------------*/
4976 createLabel (symbol * label, ast * stmnt)
4979 char name[SDCC_NAME_MAX + 1];
4982 /* must create fresh symbol if the symbol name */
4983 /* exists in the symbol table, since there can */
4984 /* be a variable with the same name as the labl */
4985 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4986 (csym->level == label->level))
4987 label = newSymbol (label->name, label->level);
4989 /* change the name before putting it in add _ */
4990 SNPRINTF(name, sizeof(name), "%s", label->name);
4992 /* put the label in the LabelSymbol table */
4993 /* but first check if a label of the same */
4995 if ((csym = findSym (LabelTab, NULL, name)))
4996 werror (E_DUPLICATE_LABEL, label->name);
4998 addSym (LabelTab, label, name, label->level, 0, 0);
5002 label->key = labelKey++;
5003 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5009 /*-----------------------------------------------------------------*/
5010 /* createCase - generates the parsetree for a case statement */
5011 /*-----------------------------------------------------------------*/
5013 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5015 char caseLbl[SDCC_NAME_MAX + 1];
5019 /* if the switch statement does not exist */
5020 /* then case is out of context */
5023 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5027 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5028 /* if not a constant then error */
5029 if (!IS_LITERAL (caseVal->ftype))
5031 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5035 /* if not a integer than error */
5036 if (!IS_INTEGRAL (caseVal->ftype))
5038 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5042 /* find the end of the switch values chain */
5043 if (!(val = swStat->values.switchVals.swVals))
5044 swStat->values.switchVals.swVals = caseVal->opval.val;
5047 /* also order the cases according to value */
5049 int cVal = (int) ulFromVal (caseVal->opval.val);
5050 while (val && (int) ulFromVal (val) < cVal)
5056 /* if we reached the end then */
5059 pval->next = caseVal->opval.val;
5061 else if ((int) ulFromVal (val) == cVal)
5063 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5069 /* we found a value greater than */
5070 /* the current value we must add this */
5071 /* before the value */
5072 caseVal->opval.val->next = val;
5074 /* if this was the first in chain */
5075 if (swStat->values.switchVals.swVals == val)
5076 swStat->values.switchVals.swVals =
5079 pval->next = caseVal->opval.val;
5084 /* create the case label */
5085 SNPRINTF(caseLbl, sizeof(caseLbl),
5087 swStat->values.switchVals.swNum,
5088 (int) ulFromVal (caseVal->opval.val));
5090 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5095 /*-----------------------------------------------------------------*/
5096 /* createDefault - creates the parse tree for the default statement */
5097 /*-----------------------------------------------------------------*/
5099 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5101 char defLbl[SDCC_NAME_MAX + 1];
5103 /* if the switch statement does not exist */
5104 /* then case is out of context */
5107 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5111 if (swStat->values.switchVals.swDefault)
5113 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5118 /* turn on the default flag */
5119 swStat->values.switchVals.swDefault = 1;
5121 /* create the label */
5122 SNPRINTF (defLbl, sizeof(defLbl),
5123 "_default_%d", swStat->values.switchVals.swNum);
5124 return createLabel (newSymbol (defLbl, 0), stmnt);
5127 /*-----------------------------------------------------------------*/
5128 /* createIf - creates the parsetree for the if statement */
5129 /*-----------------------------------------------------------------*/
5131 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5133 static int Lblnum = 0;
5135 symbol *ifTrue, *ifFalse, *ifEnd;
5137 /* if neither exists */
5138 if (!elseBody && !ifBody) {
5139 // if there are no side effects (i++, j() etc)
5140 if (!hasSEFcalls(condAst)) {
5145 /* create the labels */
5146 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5147 ifFalse = newSymbol (buffer, NestLevel);
5148 /* if no else body then end == false */
5153 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5154 ifEnd = newSymbol (buffer, NestLevel);
5157 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5158 ifTrue = newSymbol (buffer, NestLevel);
5162 /* attach the ifTrue label to the top of it body */
5163 ifBody = createLabel (ifTrue, ifBody);
5164 /* attach a goto end to the ifBody if else is present */
5167 ifBody = newNode (NULLOP, ifBody,
5169 newAst_VALUE (symbolVal (ifEnd)),
5171 /* put the elseLabel on the else body */
5172 elseBody = createLabel (ifFalse, elseBody);
5173 /* out the end at the end of the body */
5174 elseBody = newNode (NULLOP,
5176 createLabel (ifEnd, NULL));
5180 ifBody = newNode (NULLOP, ifBody,
5181 createLabel (ifFalse, NULL));
5183 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5184 if (IS_IFX (condAst))
5187 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5189 return newNode (NULLOP, ifTree,
5190 newNode (NULLOP, ifBody, elseBody));
5194 /*-----------------------------------------------------------------*/
5195 /* createDo - creates parse tree for do */
5198 /* _docontinue_n: */
5199 /* condition_expression +-> trueLabel -> _dobody_n */
5201 /* +-> falseLabel-> _dobreak_n */
5203 /*-----------------------------------------------------------------*/
5205 createDo (symbol * trueLabel, symbol * continueLabel,
5206 symbol * falseLabel, ast * condAst, ast * doBody)
5211 /* if the body does not exist then it is simple */
5214 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5215 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5216 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5217 doTree->trueLabel = continueLabel;
5218 doTree->falseLabel = NULL;
5220 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5224 /* otherwise we have a body */
5225 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5227 /* attach the body label to the top */
5228 doBody = createLabel (trueLabel, doBody);
5229 /* attach the continue label to end of body */
5230 doBody = newNode (NULLOP, doBody,
5231 createLabel (continueLabel, NULL));
5233 /* now put the break label at the end */
5234 if (IS_IFX (condAst))
5237 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5239 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5241 /* putting it together */
5242 return newNode (NULLOP, doBody, doTree);
5245 /*-----------------------------------------------------------------*/
5246 /* createFor - creates parse tree for 'for' statement */
5249 /* condExpr +-> trueLabel -> _forbody_n */
5251 /* +-> falseLabel-> _forbreak_n */
5254 /* _forcontinue_n: */
5256 /* goto _forcond_n ; */
5258 /*-----------------------------------------------------------------*/
5260 createFor (symbol * trueLabel, symbol * continueLabel,
5261 symbol * falseLabel, symbol * condLabel,
5262 ast * initExpr, ast * condExpr, ast * loopExpr,
5267 /* if loopexpression not present then we can generate it */
5268 /* the same way as a while */
5270 return newNode (NULLOP, initExpr,
5271 createWhile (trueLabel, continueLabel,
5272 falseLabel, condExpr, forBody));
5273 /* vanilla for statement */
5274 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5276 if (condExpr && !IS_IFX (condExpr))
5277 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5280 /* attach condition label to condition */
5281 condExpr = createLabel (condLabel, condExpr);
5283 /* attach body label to body */
5284 forBody = createLabel (trueLabel, forBody);
5286 /* attach continue to forLoop expression & attach */
5287 /* goto the forcond @ and of loopExpression */
5288 loopExpr = createLabel (continueLabel,
5292 newAst_VALUE (symbolVal (condLabel)),
5294 /* now start putting them together */
5295 forTree = newNode (NULLOP, initExpr, condExpr);
5296 forTree = newNode (NULLOP, forTree, forBody);
5297 forTree = newNode (NULLOP, forTree, loopExpr);
5298 /* finally add the break label */
5299 forTree = newNode (NULLOP, forTree,
5300 createLabel (falseLabel, NULL));
5304 /*-----------------------------------------------------------------*/
5305 /* createWhile - creates parse tree for while statement */
5306 /* the while statement will be created as follows */
5308 /* _while_continue_n: */
5309 /* condition_expression +-> trueLabel -> _while_boby_n */
5311 /* +-> falseLabel -> _while_break_n */
5312 /* _while_body_n: */
5314 /* goto _while_continue_n */
5315 /* _while_break_n: */
5316 /*-----------------------------------------------------------------*/
5318 createWhile (symbol * trueLabel, symbol * continueLabel,
5319 symbol * falseLabel, ast * condExpr, ast * whileBody)
5323 /* put the continue label */
5324 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5325 condExpr = createLabel (continueLabel, condExpr);
5326 condExpr->lineno = 0;
5328 /* put the body label in front of the body */
5329 whileBody = createLabel (trueLabel, whileBody);
5330 whileBody->lineno = 0;
5331 /* put a jump to continue at the end of the body */
5332 /* and put break label at the end of the body */
5333 whileBody = newNode (NULLOP,
5336 newAst_VALUE (symbolVal (continueLabel)),
5337 createLabel (falseLabel, NULL)));
5339 /* put it all together */
5340 if (IS_IFX (condExpr))
5341 whileTree = condExpr;
5344 whileTree = newNode (IFX, condExpr, NULL);
5345 /* put the true & false labels in place */
5346 whileTree->trueLabel = trueLabel;
5347 whileTree->falseLabel = falseLabel;
5350 return newNode (NULLOP, whileTree, whileBody);
5353 /*-----------------------------------------------------------------*/
5354 /* isShiftRightLitVal _BitAndLitVal - helper function */
5355 /*-----------------------------------------------------------------*/
5357 isShiftRightLitVal_BitAndLitVal (ast * tree)
5359 /* if this is not a bit and */
5360 if (!IS_BITAND (tree))
5363 /* will look for tree of the form
5364 ( expr >> litval2) & litval1 */
5365 if (!IS_AST_LIT_VALUE (tree->right))
5368 if (!IS_RIGHT_OP (tree->left))
5371 if (!IS_AST_LIT_VALUE (tree->left->right))
5374 return tree->left->left;
5377 /*-----------------------------------------------------------------*/
5378 /* isBitAndPowOf2 - helper function */
5379 /*-----------------------------------------------------------------*/
5381 isBitAndPow2 (ast * tree)
5383 /* if this is not a bit and */
5384 if (!IS_BITAND (tree))
5387 /* will look for tree of the form
5388 ( expr & (1 << litval) */
5389 if (!IS_AST_LIT_VALUE (tree->right))
5392 return powof2 (AST_ULONG_VALUE (tree->right));
5395 /*-----------------------------------------------------------------*/
5396 /* optimizeGetHbit - get highest order bit of the expression */
5397 /*-----------------------------------------------------------------*/
5399 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5404 expr = isShiftRightLitVal_BitAndLitVal(tree);
5407 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5408 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5409 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5412 if (!expr && (resultType == RESULT_TYPE_BIT))
5415 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5421 /* make sure the port supports GETHBIT */
5422 if (port->hasExtBitOp
5423 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5426 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5429 /*-----------------------------------------------------------------*/
5430 /* optimizeGetAbit - get a single bit of the expression */
5431 /*-----------------------------------------------------------------*/
5433 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5438 expr = isShiftRightLitVal_BitAndLitVal(tree);
5441 if (AST_ULONG_VALUE (tree->right) != 1)
5443 count = tree->left->right;
5445 if (!expr && (resultType == RESULT_TYPE_BIT))
5447 int p2 = isBitAndPow2 (tree);
5451 count = newAst_VALUE (valueFromLit (p2));
5457 /* make sure the port supports GETABIT */
5458 if (port->hasExtBitOp
5459 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5462 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5466 /*-----------------------------------------------------------------*/
5467 /* optimizeGetByte - get a byte of the expression */
5468 /*-----------------------------------------------------------------*/
5470 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5476 expr = isShiftRightLitVal_BitAndLitVal(tree);
5479 i = AST_ULONG_VALUE (tree->left->right);
5480 count = tree->left->right;
5481 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5484 if (!expr && resultType == RESULT_TYPE_CHAR)
5486 /* if this is a right shift over a multiple of 8 */
5487 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5489 i = AST_ULONG_VALUE (tree->right);
5490 count = tree->right;
5494 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5497 /* make sure the port supports GETBYTE */
5498 if (port->hasExtBitOp
5499 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5502 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5505 /*-----------------------------------------------------------------*/
5506 /* optimizeGetWord - get two bytes of the expression */
5507 /*-----------------------------------------------------------------*/
5509 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5515 expr = isShiftRightLitVal_BitAndLitVal(tree);
5518 i = AST_ULONG_VALUE (tree->left->right);
5519 count = tree->left->right;
5520 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5523 if (!expr && resultType == RESULT_TYPE_INT)
5525 /* if this is a right shift over a multiple of 8 */
5526 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5528 i = AST_ULONG_VALUE (tree->right);
5529 count = tree->right;
5533 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5536 /* make sure the port supports GETWORD */
5537 if (port->hasExtBitOp
5538 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5541 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5544 /*-----------------------------------------------------------------*/
5545 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5546 /*-----------------------------------------------------------------*/
5548 optimizeRRCRLC (ast * root)
5550 /* will look for trees of the form
5551 (?expr << 1) | (?expr >> 7) or
5552 (?expr >> 7) | (?expr << 1) will make that
5553 into a RLC : operation ..
5555 (?expr >> 1) | (?expr << 7) or
5556 (?expr << 7) | (?expr >> 1) will make that
5557 into a RRC operation
5558 note : by 7 I mean (number of bits required to hold the
5560 /* if the root operation is not a | operation then not */
5561 if (!IS_BITOR (root))
5564 /* I have to think of a better way to match patterns this sucks */
5565 /* that aside let's start looking for the first case : I use a
5566 negative check a lot to improve the efficiency */
5567 /* (?expr << 1) | (?expr >> 7) */
5568 if (IS_LEFT_OP (root->left) &&
5569 IS_RIGHT_OP (root->right))
5572 if (!SPEC_USIGN (TETYPE (root->left->left)))
5575 if (!IS_AST_LIT_VALUE (root->left->right) ||
5576 !IS_AST_LIT_VALUE (root->right->right))
5579 /* make sure it is the same expression */
5580 if (!isAstEqual (root->left->left,
5584 if (AST_ULONG_VALUE (root->left->right) != 1)
5587 if (AST_ULONG_VALUE (root->right->right) !=
5588 (getSize (TTYPE (root->left->left)) * 8 - 1))
5591 /* make sure the port supports RLC */
5592 if (port->hasExtBitOp
5593 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5596 /* whew got the first case : create the AST */
5597 return newNode (RLC, root->left->left, NULL);
5601 /* check for second case */
5602 /* (?expr >> 7) | (?expr << 1) */
5603 if (IS_LEFT_OP (root->right) &&
5604 IS_RIGHT_OP (root->left))
5607 if (!SPEC_USIGN (TETYPE (root->left->left)))
5610 if (!IS_AST_LIT_VALUE (root->left->right) ||
5611 !IS_AST_LIT_VALUE (root->right->right))
5614 /* make sure it is the same symbol */
5615 if (!isAstEqual (root->left->left,
5619 if (AST_ULONG_VALUE (root->right->right) != 1)
5622 if (AST_ULONG_VALUE (root->left->right) !=
5623 (getSize (TTYPE (root->left->left)) * 8 - 1))
5626 /* make sure the port supports RLC */
5627 if (port->hasExtBitOp
5628 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5631 /* whew got the first case : create the AST */
5632 return newNode (RLC, root->left->left, NULL);
5637 /* third case for RRC */
5638 /* (?symbol >> 1) | (?symbol << 7) */
5639 if (IS_LEFT_OP (root->right) &&
5640 IS_RIGHT_OP (root->left))
5643 if (!SPEC_USIGN (TETYPE (root->left->left)))
5646 if (!IS_AST_LIT_VALUE (root->left->right) ||
5647 !IS_AST_LIT_VALUE (root->right->right))
5650 /* make sure it is the same symbol */
5651 if (!isAstEqual (root->left->left,
5655 if (AST_ULONG_VALUE (root->left->right) != 1)
5658 if (AST_ULONG_VALUE (root->right->right) !=
5659 (getSize (TTYPE (root->left->left)) * 8 - 1))
5662 /* make sure the port supports RRC */
5663 if (port->hasExtBitOp
5664 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5667 /* whew got the first case : create the AST */
5668 return newNode (RRC, root->left->left, NULL);
5672 /* fourth and last case for now */
5673 /* (?symbol << 7) | (?symbol >> 1) */
5674 if (IS_RIGHT_OP (root->right) &&
5675 IS_LEFT_OP (root->left))
5678 if (!SPEC_USIGN (TETYPE (root->left->left)))
5681 if (!IS_AST_LIT_VALUE (root->left->right) ||
5682 !IS_AST_LIT_VALUE (root->right->right))
5685 /* make sure it is the same symbol */
5686 if (!isAstEqual (root->left->left,
5690 if (AST_ULONG_VALUE (root->right->right) != 1)
5693 if (AST_ULONG_VALUE (root->left->right) !=
5694 (getSize (TTYPE (root->left->left)) * 8 - 1))
5697 /* make sure the port supports RRC */
5698 if (port->hasExtBitOp
5699 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5702 /* whew got the first case : create the AST */
5703 return newNode (RRC, root->left->left, NULL);
5707 /* not found return root */
5711 /*-----------------------------------------------------------------*/
5712 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5713 /*-----------------------------------------------------------------*/
5715 optimizeSWAP (ast * root)
5717 /* will look for trees of the form
5718 (?expr << 4) | (?expr >> 4) or
5719 (?expr >> 4) | (?expr << 4) will make that
5720 into a SWAP : operation ..
5721 note : by 4 I mean (number of bits required to hold the
5723 /* if the root operation is not a | operation then not */
5724 if (!IS_BITOR (root))
5727 /* (?expr << 4) | (?expr >> 4) */
5728 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5729 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5732 if (!SPEC_USIGN (TETYPE (root->left->left)))
5735 if (!IS_AST_LIT_VALUE (root->left->right) ||
5736 !IS_AST_LIT_VALUE (root->right->right))
5739 /* make sure it is the same expression */
5740 if (!isAstEqual (root->left->left,
5744 if (AST_ULONG_VALUE (root->left->right) !=
5745 (getSize (TTYPE (root->left->left)) * 4))
5748 if (AST_ULONG_VALUE (root->right->right) !=
5749 (getSize (TTYPE (root->left->left)) * 4))
5752 /* make sure the port supports SWAP */
5753 if (port->hasExtBitOp
5754 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5757 /* found it : create the AST */
5758 return newNode (SWAP, root->left->left, NULL);
5762 /* not found return root */
5766 /*-----------------------------------------------------------------*/
5767 /* optimizeCompare - optimizes compares for bit variables */
5768 /*-----------------------------------------------------------------*/
5770 optimizeCompare (ast * root)
5772 ast *optExpr = NULL;
5775 unsigned int litValue;
5777 /* if nothing then return nothing */
5781 /* if not a compare op then do leaves */
5782 if (!IS_COMPARE_OP (root))
5784 root->left = optimizeCompare (root->left);
5785 root->right = optimizeCompare (root->right);
5789 /* if left & right are the same then depending
5790 of the operation do */
5791 if (isAstEqual (root->left, root->right))
5793 switch (root->opval.op)
5798 optExpr = newAst_VALUE (constCharVal (0));
5803 optExpr = newAst_VALUE (constCharVal (1));
5807 return decorateType (optExpr, RESULT_TYPE_NONE);
5810 vleft = (root->left->type == EX_VALUE ?
5811 root->left->opval.val : NULL);
5813 vright = (root->right->type == EX_VALUE ?
5814 root->right->opval.val : NULL);
5816 /* if left is a BITVAR in BITSPACE */
5817 /* and right is a LITERAL then */
5818 /* optimize else do nothing */
5819 if (vleft && vright &&
5820 IS_BITVAR (vleft->etype) &&
5821 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5822 IS_LITERAL (vright->etype))
5825 /* if right side > 1 then comparison may never succeed */
5826 if ((litValue = (int) ulFromVal (vright)) > 1)
5828 werror (W_BAD_COMPARE);
5834 switch (root->opval.op)
5836 case '>': /* bit value greater than 1 cannot be */
5837 werror (W_BAD_COMPARE);
5841 case '<': /* bit value < 1 means 0 */
5843 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5846 case LE_OP: /* bit value <= 1 means no check */
5847 optExpr = newAst_VALUE (vright);
5850 case GE_OP: /* bit value >= 1 means only check for = */
5852 optExpr = newAst_VALUE (vleft);
5857 { /* literal is zero */
5858 switch (root->opval.op)
5860 case '<': /* bit value < 0 cannot be */
5861 werror (W_BAD_COMPARE);
5865 case '>': /* bit value > 0 means 1 */
5867 optExpr = newAst_VALUE (vleft);
5870 case LE_OP: /* bit value <= 0 means no check */
5871 case GE_OP: /* bit value >= 0 means no check */
5872 werror (W_BAD_COMPARE);
5876 case EQ_OP: /* bit == 0 means ! of bit */
5877 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5881 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5882 } /* end-of-if of BITVAR */
5888 /*-----------------------------------------------------------------*/
5889 /* addSymToBlock : adds the symbol to the first block we find */
5890 /*-----------------------------------------------------------------*/
5892 addSymToBlock (symbol * sym, ast * tree)
5894 /* reached end of tree or a leaf */
5895 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5899 if (IS_AST_OP (tree) &&
5900 tree->opval.op == BLOCK)
5903 symbol *lsym = copySymbol (sym);
5905 lsym->next = AST_VALUES (tree, sym);
5906 AST_VALUES (tree, sym) = lsym;
5910 addSymToBlock (sym, tree->left);
5911 addSymToBlock (sym, tree->right);
5914 /*-----------------------------------------------------------------*/
5915 /* processRegParms - do processing for register parameters */
5916 /*-----------------------------------------------------------------*/
5918 processRegParms (value * args, ast * body)
5922 if (IS_REGPARM (args->etype))
5923 addSymToBlock (args->sym, body);
5928 /*-----------------------------------------------------------------*/
5929 /* resetParmKey - resets the operandkeys for the symbols */
5930 /*-----------------------------------------------------------------*/
5931 DEFSETFUNC (resetParmKey)
5944 /*------------------------------------------------------------------*/
5945 /* fixupInlineLabel - change a label in an inlined function so that */
5946 /* it is always unique no matter how many times */
5947 /* the function is inlined. */
5948 /*------------------------------------------------------------------*/
5950 fixupInlineLabel (symbol * sym)
5952 char name[SDCC_NAME_MAX + 1];
5954 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5955 strcpy (sym->name, name);
5959 /*------------------------------------------------------------------*/
5960 /* copyAstLoc - copy location information (file, line, block, etc.) */
5961 /* from one ast node to another */
5962 /*------------------------------------------------------------------*/
5964 copyAstLoc (ast * dest, ast * src)
5966 dest->lineno = src->lineno;
5967 dest->filename = src->filename;
5968 dest->level = src->level;
5969 dest->block = src->block;
5970 dest->seqPoint = src->seqPoint;
5975 /*-----------------------------------------------------------------*/
5976 /* fixupInline - perform various fixups on an inline function tree */
5977 /* to take into account that it is no longer a */
5978 /* stand-alone function. */
5979 /*-----------------------------------------------------------------*/
5981 fixupInline (ast * tree, int level)
5983 tree->block = currBlockno;
5985 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
5992 /* Add any declared variables back into the symbol table */
5993 decls = tree->values.sym;
5996 decls->level = level;
5997 decls->block = currBlockno;
5998 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
5999 decls = decls->next;
6003 tree->level = level;
6005 /* Update symbols */
6006 if (IS_AST_VALUE (tree) &&
6007 tree->opval.val->sym)
6009 symbol * sym = tree->opval.val->sym;
6012 sym->block = currBlockno;
6015 SYM_SPIL_LOC (sym) = NULL;
6018 /* If the symbol is a label, we need to renumber it */
6020 fixupInlineLabel (sym);
6023 /* Update IFX target labels */
6024 if (tree->type == EX_OP && tree->opval.op == IFX)
6026 if (tree->trueLabel)
6027 fixupInlineLabel (tree->trueLabel);
6028 if (tree->falseLabel)
6029 fixupInlineLabel (tree->falseLabel);
6032 /* Replace RETURN with optional assignment and a GOTO to the end */
6033 /* of the inlined function */
6034 if (tree->type == EX_OP && tree->opval.op == RETURN)
6036 ast * assignTree = NULL;
6039 if (inlineState.retsym && tree->right)
6041 assignTree = newNode ('=',
6042 newAst_VALUE (symbolVal (inlineState.retsym)),
6044 copyAstLoc (assignTree, tree);
6047 gotoTree = newNode (GOTO,
6048 newAst_VALUE (symbolVal (inlineState.retlab)),
6050 copyAstLoc (gotoTree, tree);
6052 tree->opval.op = NULLOP;
6053 tree->left = assignTree;
6054 tree->right = gotoTree;
6057 /* Update any children */
6059 fixupInline (tree->left, level);
6061 fixupInline (tree->right, level);
6063 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6065 symbol * label = tree->left->opval.val->sym;
6067 label->key = labelKey++;
6068 /* Add this label back into the symbol table */
6069 addSym (LabelTab, label, label->name, label->level, 0, 0);
6073 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6079 /*-----------------------------------------------------------------*/
6080 /* inlineAddDecl - add a variable declaration to an ast block. It */
6081 /* is also added to the symbol table if addSymTab */
6083 /*-----------------------------------------------------------------*/
6085 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6088 SYM_SPIL_LOC (sym) = NULL;
6092 symbol **decl = &(block->values.sym);
6094 sym->level = block->level;
6095 sym->block = block->block;
6099 if (strcmp ((*decl)->name, sym->name) == 0)
6101 decl = &( (*decl)->next );
6107 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6113 /*-----------------------------------------------------------------*/
6114 /* inlineTempVar - create a temporary variable for inlining */
6115 /*-----------------------------------------------------------------*/
6117 inlineTempVar (sym_link * type, int level)
6121 sym = newSymbol (genSymName(level), level );
6122 sym->type = copyLinkChain (type);
6123 sym->etype = getSpec(sym->type);
6124 SPEC_SCLS (sym->etype) = S_AUTO;
6125 SPEC_OCLS (sym->etype) = NULL;
6126 SPEC_EXTR (sym->etype) = 0;
6127 SPEC_STAT (sym->etype) = 0;
6128 if IS_SPEC (sym->type)
6129 SPEC_VOLATILE (sym->type) = 0;
6131 DCL_PTR_VOLATILE (sym->type) = 0;
6132 SPEC_ABSA (sym->etype) = 0;
6138 /*-----------------------------------------------------------------*/
6139 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6140 /*-----------------------------------------------------------------*/
6142 inlineFindParmRecurse (ast * parms, int *index)
6147 if (parms->type == EX_OP && parms->opval.op == PARAM)
6151 p=inlineFindParmRecurse (parms->left, index);
6154 p=inlineFindParmRecurse (parms->right, index);
6165 /*-----------------------------------------------------------------*/
6166 /* inlineFindParm - search an ast tree of parameters to find one */
6167 /* at a particular index (0=first parameter). */
6168 /* Returns NULL if not found. */
6169 /*-----------------------------------------------------------------*/
6171 inlineFindParm (ast * parms, int index)
6173 return inlineFindParmRecurse (parms, &index);
6176 /*-----------------------------------------------------------------*/
6177 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6178 /*-----------------------------------------------------------------*/
6180 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6187 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6188 if (tempBlockno > maxBlockno)
6189 maxBlockno = tempBlockno;
6191 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6192 if (tempBlockno > maxBlockno)
6193 maxBlockno = tempBlockno;
6195 if (tree->block > maxBlockno)
6196 maxBlockno = tree->block;
6203 /*-----------------------------------------------------------------*/
6204 /* expandInlineFuncs - replace calls to inline functions with the */
6205 /* function itself */
6206 /*-----------------------------------------------------------------*/
6208 expandInlineFuncs (ast * tree, ast * block)
6210 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6211 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6213 symbol * func = tree->left->opval.val->sym;
6216 /* The symbol is probably not bound yet, so find the real one */
6217 csym = findSymWithLevel (SymbolTab, func);
6221 /* Is this an inline function that we can inline? */
6222 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6224 symbol * retsym = NULL;
6232 /* Generate a label for the inlined function to branch to */
6233 /* in case it contains a return statement */
6234 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6237 inlineState.retlab = retlab;
6239 /* Build the subtree for the inlined function in the form: */
6240 /* { //inlinetree block */
6241 /* { //inlinetree2 block */
6242 /* inline_function_code; */
6246 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6247 copyAstLoc (temptree, tree);
6248 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6249 copyAstLoc (temptree, tree);
6250 temptree = newNode (BLOCK, NULL, temptree);
6251 copyAstLoc (temptree, tree);
6252 inlinetree2 = temptree;
6253 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6254 copyAstLoc (inlinetree, tree);
6256 /* To pass parameters to the inlined function, we need some */
6257 /* intermediate variables. This avoids scoping problems */
6258 /* when the parameter declaration names are used differently */
6259 /* during the function call. For example, a function */
6260 /* declared as func(int x, int y) but called as func(y,x). */
6261 /* { //inlinetree block */
6262 /* type1 temparg1; */
6264 /* typen tempargn; */
6265 /* temparg1 = argument1; */
6267 /* tempargn = argumentn; */
6268 /* { //inlinetree2 block */
6272 /* param1 = temparg1; */
6274 /* paramn = tempargn; */
6275 /* inline_function_code; */
6279 args = FUNC_ARGS (func->type);
6286 symbol * parm = copySymbol (args->sym);
6288 temparg = inlineTempVar (args->sym->type, tree->level+1);
6289 inlineAddDecl (temparg, inlinetree, FALSE);
6291 passedarg = inlineFindParm (tree->right, argIndex);
6292 assigntree = newNode ('=',
6293 newAst_VALUE (symbolVal (temparg)),
6295 inlinetree->right = newNode (NULLOP,
6299 inlineAddDecl (parm, inlinetree2, FALSE);
6302 assigntree = newNode ('=',
6303 newAst_VALUE (symbolVal (parm)),
6304 newAst_VALUE (symbolVal (temparg)));
6305 inlinetree2->right = newNode (NULLOP,
6307 inlinetree2->right);
6314 /* Handle the return type */
6315 if (!IS_VOID (func->type->next))
6317 /* Create a temporary symbol to hold the return value and */
6318 /* join it with the inlined function using the comma */
6319 /* operator. The fixupInline function will take care of */
6320 /* changing return statements into assignments to retsym. */
6321 /* (parameter passing and return label omitted for clarity) */
6322 /* rettype retsym; */
6324 /* {{inline_function_code}}, retsym */
6326 retsym = inlineTempVar (func->type->next, tree->level);
6327 inlineAddDecl (retsym, block, TRUE);
6329 tree->opval.op = ',';
6330 tree->left = inlinetree;
6331 tree->right = newAst_VALUE (symbolVal (retsym));
6335 tree->opval.op = NULLOP;
6337 tree->right = inlinetree;
6339 inlineState.retsym = retsym;
6341 /* Renumber the various internal counters on the inlined */
6342 /* function's tree nodes and symbols. Add the inlined */
6343 /* function's local variables to the appropriate scope(s). */
6344 /* Convert inlined return statements to an assignment to */
6345 /* retsym (if needed) and a goto retlab. */
6346 fixupInline (inlinetree, inlinetree->level);
6347 inlineState.count++;
6352 /* Recursively continue to search for functions to inline. */
6353 if (IS_AST_OP (tree))
6355 if (tree->opval.op == BLOCK)
6359 expandInlineFuncs (tree->left, block);
6361 expandInlineFuncs (tree->right, block);
6366 /*-----------------------------------------------------------------*/
6367 /* createFunction - This is the key node that calls the iCode for */
6368 /* generating the code for a function. Note code */
6369 /* is generated function by function, later when */
6370 /* add inter-procedural analysis this will change */
6371 /*-----------------------------------------------------------------*/
6373 createFunction (symbol * name, ast * body)
6379 iCode *piCode = NULL;
6382 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6383 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6385 /* if check function return 0 then some problem */
6386 if (checkFunction (name, NULL) == 0)
6389 /* create a dummy block if none exists */
6391 body = newNode (BLOCK, NULL, NULL);
6395 /* check if the function name already in the symbol table */
6396 if ((csym = findSym (SymbolTab, NULL, name->name)))
6399 /* special case for compiler defined functions
6400 we need to add the name to the publics list : this
6401 actually means we are now compiling the compiler
6405 addSet (&publics, name);
6410 addSymChain (&name);
6411 allocVariables (name);
6413 name->lastLine = lexLineno;
6416 /* set the stack pointer */
6417 stackPtr = -port->stack.direction * port->stack.call_overhead;
6420 if (IFFUNC_ISISR (name->type))
6421 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6423 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6425 if (options.useXstack)
6426 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6428 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6431 fetype = getSpec (name->type); /* get the specifier for the function */
6432 /* if this is a reentrant function then */
6433 if (IFFUNC_ISREENT (name->type))
6436 inlineState.count = 0;
6437 savedBlockno = currBlockno;
6438 currBlockno = inlineFindMaxBlockno (body, 0);
6439 expandInlineFuncs (body, NULL);
6440 currBlockno = savedBlockno;
6442 if (FUNC_ISINLINE (name->type))
6443 name->funcTree = copyAst (body);
6445 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6447 /* do processing for parameters that are passed in registers */
6448 processRegParms (FUNC_ARGS(name->type), body);
6450 /* set the stack pointer */
6454 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6456 /* allocate & autoinit the block variables */
6457 processBlockVars (body, &stack, ALLOCATE);
6459 /* name needs to be mangled */
6460 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6462 body = resolveSymbols (body); /* resolve the symbols */
6463 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6465 /* save the stack information */
6466 if (options.useXstack)
6467 name->xstack = SPEC_STAK (fetype) = stack;
6469 name->stack = SPEC_STAK (fetype) = stack;
6471 ex = newAst_VALUE (symbolVal (name)); /* create name */
6472 ex = newNode (FUNCTION, ex, body);
6473 ex->values.args = FUNC_ARGS(name->type);
6475 if (options.dump_tree)
6480 /* Do not generate code for inline functions unless extern also. */
6482 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6485 /* Temporary hack: always generate code for static inline functions. */
6486 /* Ideally static inline functions should only be generated if needed. */
6487 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6491 /* create the node & generate intermediate code */
6493 codeOutBuf = &code->oBuf;
6494 piCode = iCodeFromAst (ex);
6495 name->generated = 1;
6500 eBBlockFromiCode (piCode);
6502 /* if there are any statics then do them */
6505 GcurMemmap = statsg;
6506 codeOutBuf = &statsg->oBuf;
6507 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6513 /* dealloc the block variables */
6514 processBlockVars (body, &stack, DEALLOCATE);
6515 outputDebugStackSymbols();
6516 /* deallocate paramaters */
6517 deallocParms (FUNC_ARGS(name->type));
6519 if (IFFUNC_ISREENT (name->type))
6522 /* we are done freeup memory & cleanup */
6524 if (port->reset_labelKey) labelKey = 1;
6526 FUNC_HASBODY(name->type) = 1;
6527 addSet (&operKeyReset, name);
6528 applyToSet (operKeyReset, resetParmKey);
6533 cleanUpLevel (LabelTab, 0);
6534 cleanUpBlock (StructTab, 1);
6535 cleanUpBlock (TypedefTab, 1);
6537 xstack->syms = NULL;
6538 istack->syms = NULL;
6543 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6544 /*-----------------------------------------------------------------*/
6545 /* ast_print : prints the ast (for debugging purposes) */
6546 /*-----------------------------------------------------------------*/
6548 void ast_print (ast * tree, FILE *outfile, int indent)
6553 /* can print only decorated trees */
6554 if (!tree->decorated) return;
6556 /* if any child is an error | this one is an error do nothing */
6557 if (tree->isError ||
6558 (tree->left && tree->left->isError) ||
6559 (tree->right && tree->right->isError)) {
6560 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6564 /* print the line */
6565 /* if not block & function */
6566 if (tree->type == EX_OP &&
6567 (tree->opval.op != FUNCTION &&
6568 tree->opval.op != BLOCK &&
6569 tree->opval.op != NULLOP)) {
6572 if (tree->opval.op == FUNCTION) {
6574 value *args=FUNC_ARGS(tree->left->opval.val->type);
6575 fprintf(outfile,"FUNCTION (%s=%p) type (",
6576 tree->left->opval.val->name, tree);
6577 printTypeChain (tree->left->opval.val->type->next,outfile);
6578 fprintf(outfile,") args (");
6581 fprintf (outfile, ", ");
6583 printTypeChain (args ? args->type : NULL, outfile);
6585 args= args ? args->next : NULL;
6587 fprintf(outfile,")\n");
6588 ast_print(tree->left,outfile,indent);
6589 ast_print(tree->right,outfile,indent);
6592 if (tree->opval.op == BLOCK) {
6593 symbol *decls = tree->values.sym;
6594 INDENT(indent,outfile);
6595 fprintf(outfile,"{\n");
6597 INDENT(indent+2,outfile);
6598 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6599 decls->name, decls);
6600 printTypeChain(decls->type,outfile);
6601 fprintf(outfile,")\n");
6603 decls = decls->next;
6605 ast_print(tree->right,outfile,indent+2);
6606 INDENT(indent,outfile);
6607 fprintf(outfile,"}\n");
6610 if (tree->opval.op == NULLOP) {
6611 ast_print(tree->left,outfile,indent);
6612 ast_print(tree->right,outfile,indent);
6615 INDENT(indent,outfile);
6617 /*------------------------------------------------------------------*/
6618 /*----------------------------*/
6619 /* leaf has been reached */
6620 /*----------------------------*/
6621 /* if this is of type value */
6622 /* just get the type */
6623 if (tree->type == EX_VALUE) {
6625 if (IS_LITERAL (tree->opval.val->etype)) {
6626 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6627 if (SPEC_USIGN (tree->opval.val->etype))
6628 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6630 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6631 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6632 floatFromVal(tree->opval.val));
6633 } else if (tree->opval.val->sym) {
6634 /* if the undefined flag is set then give error message */
6635 if (tree->opval.val->sym->undefined) {
6636 fprintf(outfile,"UNDEFINED SYMBOL ");
6638 fprintf(outfile,"SYMBOL ");
6640 fprintf(outfile,"(%s=%p @ %p)",
6641 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6644 fprintf(outfile," type (");
6645 printTypeChain(tree->ftype,outfile);
6646 fprintf(outfile,")\n");
6648 fprintf(outfile,"\n");
6653 /* if type link for the case of cast */
6654 if (tree->type == EX_LINK) {
6655 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6656 printTypeChain(tree->opval.lnk,outfile);
6657 fprintf(outfile,")\n");
6662 /* depending on type of operator do */
6664 switch (tree->opval.op) {
6665 /*------------------------------------------------------------------*/
6666 /*----------------------------*/
6668 /*----------------------------*/
6670 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6671 printTypeChain(tree->ftype,outfile);
6672 fprintf(outfile,")\n");
6673 ast_print(tree->left,outfile,indent+2);
6674 ast_print(tree->right,outfile,indent+2);
6677 /*------------------------------------------------------------------*/
6678 /*----------------------------*/
6680 /*----------------------------*/
6682 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6683 printTypeChain(tree->ftype,outfile);
6684 fprintf(outfile,")\n");
6685 ast_print(tree->left,outfile,indent+2);
6686 ast_print(tree->right,outfile,indent+2);
6689 /*------------------------------------------------------------------*/
6690 /*----------------------------*/
6691 /* struct/union pointer */
6692 /*----------------------------*/
6694 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6695 printTypeChain(tree->ftype,outfile);
6696 fprintf(outfile,")\n");
6697 ast_print(tree->left,outfile,indent+2);
6698 ast_print(tree->right,outfile,indent+2);
6701 /*------------------------------------------------------------------*/
6702 /*----------------------------*/
6703 /* ++/-- operation */
6704 /*----------------------------*/
6707 fprintf(outfile,"post-");
6709 fprintf(outfile,"pre-");
6710 fprintf(outfile,"INC_OP (%p) type (",tree);
6711 printTypeChain(tree->ftype,outfile);
6712 fprintf(outfile,")\n");
6713 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6714 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6719 fprintf(outfile,"post-");
6721 fprintf(outfile,"pre-");
6722 fprintf(outfile,"DEC_OP (%p) type (",tree);
6723 printTypeChain(tree->ftype,outfile);
6724 fprintf(outfile,")\n");
6725 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6726 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6729 /*------------------------------------------------------------------*/
6730 /*----------------------------*/
6732 /*----------------------------*/
6735 fprintf(outfile,"& (%p) type (",tree);
6736 printTypeChain(tree->ftype,outfile);
6737 fprintf(outfile,")\n");
6738 ast_print(tree->left,outfile,indent+2);
6739 ast_print(tree->right,outfile,indent+2);
6741 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6742 printTypeChain(tree->ftype,outfile);
6743 fprintf(outfile,")\n");
6744 ast_print(tree->left,outfile,indent+2);
6745 ast_print(tree->right,outfile,indent+2);
6748 /*----------------------------*/
6750 /*----------------------------*/
6752 fprintf(outfile,"OR (%p) type (",tree);
6753 printTypeChain(tree->ftype,outfile);
6754 fprintf(outfile,")\n");
6755 ast_print(tree->left,outfile,indent+2);
6756 ast_print(tree->right,outfile,indent+2);
6758 /*------------------------------------------------------------------*/
6759 /*----------------------------*/
6761 /*----------------------------*/
6763 fprintf(outfile,"XOR (%p) type (",tree);
6764 printTypeChain(tree->ftype,outfile);
6765 fprintf(outfile,")\n");
6766 ast_print(tree->left,outfile,indent+2);
6767 ast_print(tree->right,outfile,indent+2);
6770 /*------------------------------------------------------------------*/
6771 /*----------------------------*/
6773 /*----------------------------*/
6775 fprintf(outfile,"DIV (%p) type (",tree);
6776 printTypeChain(tree->ftype,outfile);
6777 fprintf(outfile,")\n");
6778 ast_print(tree->left,outfile,indent+2);
6779 ast_print(tree->right,outfile,indent+2);
6781 /*------------------------------------------------------------------*/
6782 /*----------------------------*/
6784 /*----------------------------*/
6786 fprintf(outfile,"MOD (%p) type (",tree);
6787 printTypeChain(tree->ftype,outfile);
6788 fprintf(outfile,")\n");
6789 ast_print(tree->left,outfile,indent+2);
6790 ast_print(tree->right,outfile,indent+2);
6793 /*------------------------------------------------------------------*/
6794 /*----------------------------*/
6795 /* address dereference */
6796 /*----------------------------*/
6797 case '*': /* can be unary : if right is null then unary operation */
6799 fprintf(outfile,"DEREF (%p) type (",tree);
6800 printTypeChain(tree->ftype,outfile);
6801 fprintf(outfile,")\n");
6802 ast_print(tree->left,outfile,indent+2);
6805 /*------------------------------------------------------------------*/
6806 /*----------------------------*/
6807 /* multiplication */
6808 /*----------------------------*/
6809 fprintf(outfile,"MULT (%p) type (",tree);
6810 printTypeChain(tree->ftype,outfile);
6811 fprintf(outfile,")\n");
6812 ast_print(tree->left,outfile,indent+2);
6813 ast_print(tree->right,outfile,indent+2);
6817 /*------------------------------------------------------------------*/
6818 /*----------------------------*/
6819 /* unary '+' operator */
6820 /*----------------------------*/
6824 fprintf(outfile,"UPLUS (%p) type (",tree);
6825 printTypeChain(tree->ftype,outfile);
6826 fprintf(outfile,")\n");
6827 ast_print(tree->left,outfile,indent+2);
6829 /*------------------------------------------------------------------*/
6830 /*----------------------------*/
6832 /*----------------------------*/
6833 fprintf(outfile,"ADD (%p) type (",tree);
6834 printTypeChain(tree->ftype,outfile);
6835 fprintf(outfile,")\n");
6836 ast_print(tree->left,outfile,indent+2);
6837 ast_print(tree->right,outfile,indent+2);
6840 /*------------------------------------------------------------------*/
6841 /*----------------------------*/
6843 /*----------------------------*/
6844 case '-': /* can be unary */
6846 fprintf(outfile,"UMINUS (%p) type (",tree);
6847 printTypeChain(tree->ftype,outfile);
6848 fprintf(outfile,")\n");
6849 ast_print(tree->left,outfile,indent+2);
6851 /*------------------------------------------------------------------*/
6852 /*----------------------------*/
6854 /*----------------------------*/
6855 fprintf(outfile,"SUB (%p) type (",tree);
6856 printTypeChain(tree->ftype,outfile);
6857 fprintf(outfile,")\n");
6858 ast_print(tree->left,outfile,indent+2);
6859 ast_print(tree->right,outfile,indent+2);
6862 /*------------------------------------------------------------------*/
6863 /*----------------------------*/
6865 /*----------------------------*/
6867 fprintf(outfile,"COMPL (%p) type (",tree);
6868 printTypeChain(tree->ftype,outfile);
6869 fprintf(outfile,")\n");
6870 ast_print(tree->left,outfile,indent+2);
6872 /*------------------------------------------------------------------*/
6873 /*----------------------------*/
6875 /*----------------------------*/
6877 fprintf(outfile,"NOT (%p) type (",tree);
6878 printTypeChain(tree->ftype,outfile);
6879 fprintf(outfile,")\n");
6880 ast_print(tree->left,outfile,indent+2);
6882 /*------------------------------------------------------------------*/
6883 /*----------------------------*/
6885 /*----------------------------*/
6887 fprintf(outfile,"RRC (%p) type (",tree);
6888 printTypeChain(tree->ftype,outfile);
6889 fprintf(outfile,")\n");
6890 ast_print(tree->left,outfile,indent+2);
6894 fprintf(outfile,"RLC (%p) type (",tree);
6895 printTypeChain(tree->ftype,outfile);
6896 fprintf(outfile,")\n");
6897 ast_print(tree->left,outfile,indent+2);
6900 fprintf(outfile,"SWAP (%p) type (",tree);
6901 printTypeChain(tree->ftype,outfile);
6902 fprintf(outfile,")\n");
6903 ast_print(tree->left,outfile,indent+2);
6906 fprintf(outfile,"GETHBIT (%p) type (",tree);
6907 printTypeChain(tree->ftype,outfile);
6908 fprintf(outfile,")\n");
6909 ast_print(tree->left,outfile,indent+2);
6912 fprintf(outfile,"GETABIT (%p) type (",tree);
6913 printTypeChain(tree->ftype,outfile);
6914 fprintf(outfile,")\n");
6915 ast_print(tree->left,outfile,indent+2);
6916 ast_print(tree->right,outfile,indent+2);
6919 fprintf(outfile,"GETBYTE (%p) type (",tree);
6920 printTypeChain(tree->ftype,outfile);
6921 fprintf(outfile,")\n");
6922 ast_print(tree->left,outfile,indent+2);
6923 ast_print(tree->right,outfile,indent+2);
6926 fprintf(outfile,"GETWORD (%p) type (",tree);
6927 printTypeChain(tree->ftype,outfile);
6928 fprintf(outfile,")\n");
6929 ast_print(tree->left,outfile,indent+2);
6930 ast_print(tree->right,outfile,indent+2);
6933 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6934 printTypeChain(tree->ftype,outfile);
6935 fprintf(outfile,")\n");
6936 ast_print(tree->left,outfile,indent+2);
6937 ast_print(tree->right,outfile,indent+2);
6940 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6941 printTypeChain(tree->ftype,outfile);
6942 fprintf(outfile,")\n");
6943 ast_print(tree->left,outfile,indent+2);
6944 ast_print(tree->right,outfile,indent+2);
6946 /*------------------------------------------------------------------*/
6947 /*----------------------------*/
6949 /*----------------------------*/
6950 case CAST: /* change the type */
6951 fprintf(outfile,"CAST (%p) from type (",tree);
6952 printTypeChain(tree->right->ftype,outfile);
6953 fprintf(outfile,") to type (");
6954 printTypeChain(tree->ftype,outfile);
6955 fprintf(outfile,")\n");
6956 ast_print(tree->right,outfile,indent+2);
6960 fprintf(outfile,"ANDAND (%p) type (",tree);
6961 printTypeChain(tree->ftype,outfile);
6962 fprintf(outfile,")\n");
6963 ast_print(tree->left,outfile,indent+2);
6964 ast_print(tree->right,outfile,indent+2);
6967 fprintf(outfile,"OROR (%p) type (",tree);
6968 printTypeChain(tree->ftype,outfile);
6969 fprintf(outfile,")\n");
6970 ast_print(tree->left,outfile,indent+2);
6971 ast_print(tree->right,outfile,indent+2);
6974 /*------------------------------------------------------------------*/
6975 /*----------------------------*/
6976 /* comparison operators */
6977 /*----------------------------*/
6979 fprintf(outfile,"GT(>) (%p) type (",tree);
6980 printTypeChain(tree->ftype,outfile);
6981 fprintf(outfile,")\n");
6982 ast_print(tree->left,outfile,indent+2);
6983 ast_print(tree->right,outfile,indent+2);
6986 fprintf(outfile,"LT(<) (%p) type (",tree);
6987 printTypeChain(tree->ftype,outfile);
6988 fprintf(outfile,")\n");
6989 ast_print(tree->left,outfile,indent+2);
6990 ast_print(tree->right,outfile,indent+2);
6993 fprintf(outfile,"LE(<=) (%p) type (",tree);
6994 printTypeChain(tree->ftype,outfile);
6995 fprintf(outfile,")\n");
6996 ast_print(tree->left,outfile,indent+2);
6997 ast_print(tree->right,outfile,indent+2);
7000 fprintf(outfile,"GE(>=) (%p) type (",tree);
7001 printTypeChain(tree->ftype,outfile);
7002 fprintf(outfile,")\n");
7003 ast_print(tree->left,outfile,indent+2);
7004 ast_print(tree->right,outfile,indent+2);
7007 fprintf(outfile,"EQ(==) (%p) type (",tree);
7008 printTypeChain(tree->ftype,outfile);
7009 fprintf(outfile,")\n");
7010 ast_print(tree->left,outfile,indent+2);
7011 ast_print(tree->right,outfile,indent+2);
7014 fprintf(outfile,"NE(!=) (%p) type (",tree);
7015 printTypeChain(tree->ftype,outfile);
7016 fprintf(outfile,")\n");
7017 ast_print(tree->left,outfile,indent+2);
7018 ast_print(tree->right,outfile,indent+2);
7019 /*------------------------------------------------------------------*/
7020 /*----------------------------*/
7022 /*----------------------------*/
7023 case SIZEOF: /* evaluate wihout code generation */
7024 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7027 /*------------------------------------------------------------------*/
7028 /*----------------------------*/
7029 /* conditional operator '?' */
7030 /*----------------------------*/
7032 fprintf(outfile,"QUEST(?) (%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);
7040 fprintf(outfile,"COLON(:) (%p) type (",tree);
7041 printTypeChain(tree->ftype,outfile);
7042 fprintf(outfile,")\n");
7043 ast_print(tree->left,outfile,indent+2);
7044 ast_print(tree->right,outfile,indent+2);
7047 /*------------------------------------------------------------------*/
7048 /*----------------------------*/
7049 /* assignment operators */
7050 /*----------------------------*/
7052 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7053 printTypeChain(tree->ftype,outfile);
7054 fprintf(outfile,")\n");
7055 ast_print(tree->left,outfile,indent+2);
7056 ast_print(tree->right,outfile,indent+2);
7059 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7060 printTypeChain(tree->ftype,outfile);
7061 fprintf(outfile,")\n");
7062 ast_print(tree->left,outfile,indent+2);
7063 ast_print(tree->right,outfile,indent+2);
7066 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7067 printTypeChain(tree->ftype,outfile);
7068 fprintf(outfile,")\n");
7069 ast_print(tree->left,outfile,indent+2);
7070 ast_print(tree->right,outfile,indent+2);
7073 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7074 printTypeChain(tree->ftype,outfile);
7075 fprintf(outfile,")\n");
7076 ast_print(tree->left,outfile,indent+2);
7077 ast_print(tree->right,outfile,indent+2);
7080 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7081 printTypeChain(tree->ftype,outfile);
7082 fprintf(outfile,")\n");
7083 ast_print(tree->left,outfile,indent+2);
7084 ast_print(tree->right,outfile,indent+2);
7087 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7088 printTypeChain(tree->ftype,outfile);
7089 fprintf(outfile,")\n");
7090 ast_print(tree->left,outfile,indent+2);
7091 ast_print(tree->right,outfile,indent+2);
7094 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7095 printTypeChain(tree->ftype,outfile);
7096 fprintf(outfile,")\n");
7097 ast_print(tree->left,outfile,indent+2);
7098 ast_print(tree->right,outfile,indent+2);
7100 /*------------------------------------------------------------------*/
7101 /*----------------------------*/
7103 /*----------------------------*/
7105 fprintf(outfile,"SUBASS(-=) (%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);
7111 /*------------------------------------------------------------------*/
7112 /*----------------------------*/
7114 /*----------------------------*/
7116 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7117 printTypeChain(tree->ftype,outfile);
7118 fprintf(outfile,")\n");
7119 ast_print(tree->left,outfile,indent+2);
7120 ast_print(tree->right,outfile,indent+2);
7122 /*------------------------------------------------------------------*/
7123 /*----------------------------*/
7124 /* straight assignemnt */
7125 /*----------------------------*/
7127 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7128 printTypeChain(tree->ftype,outfile);
7129 fprintf(outfile,")\n");
7130 ast_print(tree->left,outfile,indent+2);
7131 ast_print(tree->right,outfile,indent+2);
7133 /*------------------------------------------------------------------*/
7134 /*----------------------------*/
7135 /* comma operator */
7136 /*----------------------------*/
7138 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7139 printTypeChain(tree->ftype,outfile);
7140 fprintf(outfile,")\n");
7141 ast_print(tree->left,outfile,indent+2);
7142 ast_print(tree->right,outfile,indent+2);
7144 /*------------------------------------------------------------------*/
7145 /*----------------------------*/
7147 /*----------------------------*/
7150 fprintf(outfile,"CALL (%p) type (",tree);
7151 printTypeChain(tree->ftype,outfile);
7152 fprintf(outfile,")\n");
7153 ast_print(tree->left,outfile,indent+2);
7154 ast_print(tree->right,outfile,indent+2);
7157 fprintf(outfile,"PARMS\n");
7158 ast_print(tree->left,outfile,indent+2);
7159 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7160 ast_print(tree->right,outfile,indent+2);
7163 /*------------------------------------------------------------------*/
7164 /*----------------------------*/
7165 /* return statement */
7166 /*----------------------------*/
7168 fprintf(outfile,"RETURN (%p) type (",tree);
7170 printTypeChain(tree->right->ftype,outfile);
7172 fprintf(outfile,")\n");
7173 ast_print(tree->right,outfile,indent+2);
7175 /*------------------------------------------------------------------*/
7176 /*----------------------------*/
7177 /* label statement */
7178 /*----------------------------*/
7180 fprintf(outfile,"LABEL (%p)\n",tree);
7181 ast_print(tree->left,outfile,indent+2);
7182 ast_print(tree->right,outfile,indent);
7184 /*------------------------------------------------------------------*/
7185 /*----------------------------*/
7186 /* switch statement */
7187 /*----------------------------*/
7191 fprintf(outfile,"SWITCH (%p) ",tree);
7192 ast_print(tree->left,outfile,0);
7193 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7194 INDENT(indent+2,outfile);
7195 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7196 (int) ulFromVal(val),
7197 tree->values.switchVals.swNum,
7198 (int) ulFromVal(val));
7200 ast_print(tree->right,outfile,indent);
7203 /*------------------------------------------------------------------*/
7204 /*----------------------------*/
7206 /*----------------------------*/
7208 fprintf(outfile,"IF (%p) \n",tree);
7209 ast_print(tree->left,outfile,indent+2);
7210 if (tree->trueLabel) {
7211 INDENT(indent+2,outfile);
7212 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7214 if (tree->falseLabel) {
7215 INDENT(indent+2,outfile);
7216 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7218 ast_print(tree->right,outfile,indent+2);
7220 /*----------------------------*/
7221 /* goto Statement */
7222 /*----------------------------*/
7224 fprintf(outfile,"GOTO (%p) \n",tree);
7225 ast_print(tree->left,outfile,indent+2);
7226 fprintf(outfile,"\n");
7228 /*------------------------------------------------------------------*/
7229 /*----------------------------*/
7231 /*----------------------------*/
7233 fprintf(outfile,"FOR (%p) \n",tree);
7234 if (AST_FOR( tree, initExpr)) {
7235 INDENT(indent+2,outfile);
7236 fprintf(outfile,"INIT EXPR ");
7237 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7239 if (AST_FOR( tree, condExpr)) {
7240 INDENT(indent+2,outfile);
7241 fprintf(outfile,"COND EXPR ");
7242 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7244 if (AST_FOR( tree, loopExpr)) {
7245 INDENT(indent+2,outfile);
7246 fprintf(outfile,"LOOP EXPR ");
7247 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7249 fprintf(outfile,"FOR LOOP BODY \n");
7250 ast_print(tree->left,outfile,indent+2);
7253 fprintf(outfile,"CRITICAL (%p) \n",tree);
7254 ast_print(tree->left,outfile,indent+2);
7262 ast_print(t,stdout,0);
7265 /*-----------------------------------------------------------------*/
7266 /* astErrors : returns non-zero if errors present in tree */
7267 /*-----------------------------------------------------------------*/
7268 int astErrors(ast *t)
7277 if (t->type == EX_VALUE
7278 && t->opval.val->sym
7279 && t->opval.val->sym->undefined)
7282 errors += astErrors(t->left);
7283 errors += astErrors(t->right);