1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
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 -------------------------------------------------------------------------*/
28 /*-----------------------------------------------------------------*/
29 /* global variables */
31 set *iCodeChain = NULL;
41 symbol *returnLabel; /* function return label */
42 symbol *entryLabel; /* function entry label */
44 #if defined(__BORLANDC__) || defined(_MSC_VER)
45 #define LONG_LONG __int64
47 #define LONG_LONG long long
50 /*-----------------------------------------------------------------*/
51 /* forward definition of some functions */
52 operand *geniCodeDivision (operand *, operand *);
53 operand *geniCodeAssign (operand *, operand *, int);
54 operand *geniCodeArray (operand *, operand *,int);
55 operand *geniCodeArray2Ptr (operand *);
56 operand *geniCodeRValue (operand *, bool);
57 operand *geniCodeDerefPtr (operand *,int);
58 int isLvaluereq(int lvl);
60 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
61 /* forward definition of ic print functions */
62 PRINTFUNC (picGetValueAtAddr);
63 PRINTFUNC (picSetValueAtAddr);
64 PRINTFUNC (picAddrOf);
65 PRINTFUNC (picGeneric);
66 PRINTFUNC (picGenericOne);
68 PRINTFUNC (picAssign);
72 PRINTFUNC (picJumpTable);
73 PRINTFUNC (picInline);
74 PRINTFUNC (picReceive);
76 iCodeTable codeTable[] =
78 {'!', "not", picGenericOne, NULL},
79 {'~', "~", picGenericOne, NULL},
80 {RRC, "rrc", picGenericOne, NULL},
81 {RLC, "rlc", picGenericOne, NULL},
82 {GETHBIT, "ghbit", picGenericOne, NULL},
83 {UNARYMINUS, "-", picGenericOne, NULL},
84 {IPUSH, "push", picGenericOne, NULL},
85 {IPOP, "pop", picGenericOne, NULL},
86 {CALL, "call", picGenericOne, NULL},
87 {PCALL, "pcall", picGenericOne, NULL},
88 {FUNCTION, "proc", picGenericOne, NULL},
89 {ENDFUNCTION, "eproc", picGenericOne, NULL},
90 {RETURN, "ret", picGenericOne, NULL},
91 {'+', "+", picGeneric, NULL},
92 {'-', "-", picGeneric, NULL},
93 {'*', "*", picGeneric, NULL},
94 {'/', "/", picGeneric, NULL},
95 {'%', "%", picGeneric, NULL},
96 {'>', ">", picGeneric, NULL},
97 {'<', "<", picGeneric, NULL},
98 {LE_OP, "<=", picGeneric, NULL},
99 {GE_OP, ">=", picGeneric, NULL},
100 {EQ_OP, "==", picGeneric, NULL},
101 {NE_OP, "!=", picGeneric, NULL},
102 {AND_OP, "&&", picGeneric, NULL},
103 {OR_OP, "||", picGeneric, NULL},
104 {'^', "^", picGeneric, NULL},
105 {'|', "|", picGeneric, NULL},
106 {BITWISEAND, "&", picGeneric, NULL},
107 {LEFT_OP, "<<", picGeneric, NULL},
108 {RIGHT_OP, ">>", picGeneric, NULL},
109 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
110 {ADDRESS_OF, "&", picAddrOf, NULL},
111 {CAST, "<>", picCast, NULL},
112 {'=', ":=", picAssign, NULL},
113 {LABEL, "", picLabel, NULL},
114 {GOTO, "", picGoto, NULL},
115 {JUMPTABLE, "jtab", picJumpTable, NULL},
116 {IFX, "if", picIfx, NULL},
117 {INLINEASM, "", picInline, NULL},
118 {RECEIVE, "recv", picReceive, NULL},
119 {SEND, "send", picGenericOne, NULL},
120 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
123 /*-----------------------------------------------------------------*/
124 /* checkConstantRange: check a constant against the type */
125 /*-----------------------------------------------------------------*/
127 /* pedantic=0: allmost anything is allowed as long as the absolute
128 value is within the bit range of the type, and -1 is treated as
129 0xf..f for unsigned types (e.g. in assign)
130 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
131 pedantic>1: "char c=200" is not allowed (evaluates to -56)
134 void checkConstantRange(sym_link *ltype, double v, char *msg, int pedantic) {
135 LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
136 char message[132]="";
141 // this could be a good idea
142 if (options.pedantic)
146 if (SPEC_NOUN(ltype)==FLOAT) {
153 // if not pedantic: -1 equals to 0xf..f
154 if (SPEC_USIGN(ltype) && (!pedantic ? v!=-1 : 1)) {
160 // if very pedantic: "char c=200" is not allowed
161 if (pedantic>1 && !SPEC_USIGN(ltype)) {
162 max = max/2 + negative;
170 sprintf (message, "for %s %s in %s",
171 SPEC_USIGN(ltype) ? "unsigned" : "signed",
172 nounName(ltype), msg);
173 werror (W_CONST_RANGE, message);
180 /*-----------------------------------------------------------------*/
181 /* operandName - returns the name of the operand */
182 /*-----------------------------------------------------------------*/
184 printOperand (operand * op, FILE * file)
201 opetype = getSpec (operandType (op));
202 if (SPEC_NOUN (opetype) == V_FLOAT)
203 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
205 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
206 printTypeChain (operandType (op), file);
213 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
214 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
216 OP_LIVEFROM (op), OP_LIVETO (op),
217 OP_SYMBOL (op)->stack,
218 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
222 printTypeChain (operandType (op), file);
223 if (SPIL_LOC (op) && IS_ITEMP (op))
224 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
229 /* if assigned to registers */
230 if (OP_SYMBOL (op)->nRegs)
232 if (OP_SYMBOL (op)->isspilt)
234 if (!OP_SYMBOL (op)->remat)
235 if (OP_SYMBOL (op)->usl.spillLoc)
236 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
237 OP_SYMBOL (op)->usl.spillLoc->rname :
238 OP_SYMBOL (op)->usl.spillLoc->name));
240 fprintf (file, "[err]");
242 fprintf (file, "[remat]");
248 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
249 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
254 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
255 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
256 /* if assigned to registers */
257 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
261 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
262 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
263 OP_SYMBOL (op)->regs[i]->name :
272 printTypeChain (op->operand.typeOperand, file);
278 fprintf (file, "\n");
283 /*-----------------------------------------------------------------*/
284 /* print functions */
285 /*-----------------------------------------------------------------*/
286 PRINTFUNC (picGetValueAtAddr)
289 printOperand (IC_RESULT (ic), of);
292 printOperand (IC_LEFT (ic), of);
298 PRINTFUNC (picSetValueAtAddr)
302 printOperand (IC_LEFT (ic), of);
303 fprintf (of, "] = ");
304 printOperand (IC_RIGHT (ic), of);
308 PRINTFUNC (picAddrOf)
311 printOperand (IC_RESULT (ic), of);
312 if (IS_ITEMP (IC_LEFT (ic)))
315 fprintf (of, " = &[");
316 printOperand (IC_LEFT (ic), of);
319 if (IS_ITEMP (IC_LEFT (ic)))
320 fprintf (of, " offsetAdd ");
323 printOperand (IC_RIGHT (ic), of);
325 if (IS_ITEMP (IC_LEFT (ic)))
331 PRINTFUNC (picJumpTable)
336 fprintf (of, "%s\t", s);
337 printOperand (IC_JTCOND (ic), of);
339 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
340 sym = setNextItem (IC_JTLABELS (ic)))
341 fprintf (of, "\t\t\t%s\n", sym->name);
344 PRINTFUNC (picGeneric)
347 printOperand (IC_RESULT (ic), of);
349 printOperand (IC_LEFT (ic), of);
350 fprintf (of, " %s ", s);
351 printOperand (IC_RIGHT (ic), of);
355 PRINTFUNC (picGenericOne)
360 printOperand (IC_RESULT (ic), of);
366 fprintf (of, "%s ", s);
367 printOperand (IC_LEFT (ic), of);
370 if (!IC_RESULT (ic) && !IC_LEFT (ic))
379 printOperand (IC_RESULT (ic), of);
381 printOperand (IC_LEFT (ic), of);
382 printOperand (IC_RIGHT (ic), of);
387 PRINTFUNC (picAssign)
391 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
394 printOperand (IC_RESULT (ic), of);
396 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
399 fprintf (of, " %s ", s);
400 printOperand (IC_RIGHT (ic), of);
407 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
413 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
420 printOperand (IC_COND (ic), of);
423 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
426 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
428 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
432 PRINTFUNC (picInline)
434 fprintf (of, "%s", IC_INLINE (ic));
437 PRINTFUNC (picReceive)
439 printOperand (IC_RESULT (ic), of);
440 fprintf (of, " = %s ", s);
441 printOperand (IC_LEFT (ic), of);
445 /*-----------------------------------------------------------------*/
446 /* piCode - prints one iCode */
447 /*-----------------------------------------------------------------*/
449 piCode (void *item, FILE * of)
457 icTab = getTableEntry (ic->op);
458 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
459 ic->filename, ic->lineno,
460 ic->seq, ic->key, ic->depth, ic->supportRtn);
461 icTab->iCodePrint (of, ic, icTab->printName);
467 printiCChain(ic,stdout);
469 /*-----------------------------------------------------------------*/
470 /* printiCChain - prints intermediate code for humans */
471 /*-----------------------------------------------------------------*/
473 printiCChain (iCode * icChain, FILE * of)
480 for (loop = icChain; loop; loop = loop->next)
482 if ((icTab = getTableEntry (loop->op)))
484 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
485 loop->filename, loop->lineno,
486 loop->seq, loop->key, loop->depth, loop->supportRtn);
488 icTab->iCodePrint (of, loop, icTab->printName);
494 /*-----------------------------------------------------------------*/
495 /* newOperand - allocate, init & return a new iCode */
496 /*-----------------------------------------------------------------*/
502 op = Safe_calloc (1, sizeof (operand));
508 /*-----------------------------------------------------------------*/
509 /* newiCode - create and return a new iCode entry initialised */
510 /*-----------------------------------------------------------------*/
512 newiCode (int op, operand * left, operand * right)
516 ic = Safe_calloc (1, sizeof (iCode));
519 ic->filename = filename;
521 ic->level = scopeLevel;
523 ic->key = iCodeKey++;
525 IC_RIGHT (ic) = right;
530 /*-----------------------------------------------------------------*/
531 /* newiCode for conditional statements */
532 /*-----------------------------------------------------------------*/
534 newiCodeCondition (operand * condition,
540 if (IS_VOID(OP_SYMBOL(condition)->type)) {
541 werror(E_VOID_VALUE_USED);
544 ic = newiCode (IFX, NULL, NULL);
545 IC_COND (ic) = condition;
546 IC_TRUE (ic) = trueLabel;
547 IC_FALSE (ic) = falseLabel;
551 /*-----------------------------------------------------------------*/
552 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
553 /*-----------------------------------------------------------------*/
555 newiCodeLabelGoto (int op, symbol * label)
559 ic = newiCode (op, NULL, NULL);
561 ic->argLabel.label = label;
563 IC_RIGHT (ic) = NULL;
564 IC_RESULT (ic) = NULL;
568 /*-----------------------------------------------------------------*/
569 /* newiTemp - allocate & return a newItemp Variable */
570 /*-----------------------------------------------------------------*/
577 sprintf (buffer, "%s", s);
579 sprintf (buffer, "iTemp%d", iTempNum++);
580 itmp = newSymbol (buffer, 1);
581 strcpy (itmp->rname, itmp->name);
587 /*-----------------------------------------------------------------*/
588 /* newiTempLabel - creates a temp variable label */
589 /*-----------------------------------------------------------------*/
591 newiTempLabel (char *s)
595 /* check if this alredy exists */
596 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
600 itmplbl = newSymbol (s, 1);
603 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
604 itmplbl = newSymbol (buffer, 1);
609 itmplbl->key = labelKey++;
610 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
614 /*-----------------------------------------------------------------*/
615 /* newiTempPreheaderLabel - creates a new preheader label */
616 /*-----------------------------------------------------------------*/
618 newiTempPreheaderLabel ()
622 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
623 itmplbl = newSymbol (buffer, 1);
627 itmplbl->key = labelKey++;
628 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
633 /*-----------------------------------------------------------------*/
634 /* initiCode - initialises some iCode related stuff */
635 /*-----------------------------------------------------------------*/
642 /*-----------------------------------------------------------------*/
643 /* copyiCode - make a copy of the iCode given */
644 /*-----------------------------------------------------------------*/
646 copyiCode (iCode * ic)
648 iCode *nic = newiCode (ic->op, NULL, NULL);
650 nic->lineno = ic->lineno;
651 nic->filename = ic->filename;
652 nic->block = ic->block;
653 nic->level = ic->level;
654 nic->parmBytes = ic->parmBytes;
656 /* deal with the special cases first */
660 IC_COND (nic) = operandFromOperand (IC_COND (ic));
661 IC_TRUE (nic) = IC_TRUE (ic);
662 IC_FALSE (nic) = IC_FALSE (ic);
666 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
667 IC_JTLABELS (nic) = IC_JTLABELS (ic);
672 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
673 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
674 IC_ARGS (nic) = IC_ARGS (ic);
678 IC_INLINE (nic) = IC_INLINE (ic);
682 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
686 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
687 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
688 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
694 /*-----------------------------------------------------------------*/
695 /* getTableEntry - gets the table entry for the given operator */
696 /*-----------------------------------------------------------------*/
698 getTableEntry (int oper)
702 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
703 if (oper == codeTable[i].icode)
704 return &codeTable[i];
709 /*-----------------------------------------------------------------*/
710 /* newiTempOperand - new intermediate temp operand */
711 /*-----------------------------------------------------------------*/
713 newiTempOperand (sym_link * type, char throwType)
716 operand *op = newOperand ();
720 itmp = newiTemp (NULL);
722 etype = getSpec (type);
724 if (IS_LITERAL (etype))
727 /* copy the type information */
729 itmp->etype = getSpec (itmp->type = (throwType ? type :
730 copyLinkChain (type)));
731 if (IS_LITERAL (itmp->etype))
733 SPEC_SCLS (itmp->etype) = S_REGISTER;
734 SPEC_OCLS (itmp->etype) = reg;
737 op->operand.symOperand = itmp;
738 op->key = itmp->key = ++operandKey;
742 /*-----------------------------------------------------------------*/
743 /* operandType - returns the type chain for an operand */
744 /*-----------------------------------------------------------------*/
746 operandType (operand * op)
748 /* depending on type of operand */
753 return op->operand.valOperand->type;
756 return op->operand.symOperand->type;
759 return op->operand.typeOperand;
761 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
762 " operand type not known ");
763 assert (0); /* should never come here */
764 /* Just to keep the compiler happy */
765 return (sym_link *) 0;
769 /*-----------------------------------------------------------------*/
770 /* isParamterToCall - will return 1 if op is a parameter to args */
771 /*-----------------------------------------------------------------*/
773 isParameterToCall (value * args, operand * op)
780 isSymbolEqual (op->operand.symOperand, tval->sym))
787 /*-----------------------------------------------------------------*/
788 /* isOperandGlobal - return 1 if operand is a global variable */
789 /*-----------------------------------------------------------------*/
791 isOperandGlobal (operand * op)
799 if (op->type == SYMBOL &&
800 (op->operand.symOperand->level == 0 ||
801 IS_STATIC (op->operand.symOperand->etype) ||
802 IS_EXTERN (op->operand.symOperand->etype))
809 /*-----------------------------------------------------------------*/
810 /* isOperandVolatile - return 1 if the operand is volatile */
811 /*-----------------------------------------------------------------*/
813 isOperandVolatile (operand * op, bool chkTemp)
818 if (IS_ITEMP (op) && !chkTemp)
821 opetype = getSpec (optype = operandType (op));
823 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
826 if (IS_VOLATILE (opetype))
831 /*-----------------------------------------------------------------*/
832 /* isOperandLiteral - returns 1 if an operand contains a literal */
833 /*-----------------------------------------------------------------*/
835 isOperandLiteral (operand * op)
842 opetype = getSpec (operandType (op));
844 if (IS_LITERAL (opetype))
849 /*-----------------------------------------------------------------*/
850 /* isOperandInFarSpace - will return true if operand is in farSpace */
851 /*-----------------------------------------------------------------*/
853 isOperandInFarSpace (operand * op)
863 if (!IS_TRUE_SYMOP (op))
866 etype = SPIL_LOC (op)->etype;
872 etype = getSpec (operandType (op));
874 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
877 /*-----------------------------------------------------------------*/
878 /* isOperandOnStack - will return true if operand is on stack */
879 /*-----------------------------------------------------------------*/
881 isOperandOnStack (operand * op)
891 etype = getSpec (operandType (op));
893 return ((IN_STACK (etype)) ? TRUE : FALSE);
896 /*-----------------------------------------------------------------*/
897 /* operandLitValue - literal value of an operand */
898 /*-----------------------------------------------------------------*/
900 operandLitValue (operand * op)
902 assert (isOperandLiteral (op));
904 return floatFromVal (op->operand.valOperand);
907 /*-----------------------------------------------------------------*/
908 /* operandOperation - perforoms operations on operands */
909 /*-----------------------------------------------------------------*/
911 operandOperation (operand * left, operand * right,
912 int op, sym_link * type)
914 sym_link *let , *ret=NULL;
915 operand *retval = (operand *) 0;
917 assert (isOperandLiteral (left));
918 let = getSpec(operandType(left));
920 assert (isOperandLiteral (right));
921 ret = getSpec(operandType(left));
927 retval = operandFromValue (valCastLiteral (type,
928 operandLitValue (left) +
929 operandLitValue (right)));
932 retval = operandFromValue (valCastLiteral (type,
933 operandLitValue (left) -
934 operandLitValue (right)));
937 retval = operandFromValue (valCastLiteral (type,
938 operandLitValue (left) *
939 operandLitValue (right)));
942 if ((unsigned long) operandLitValue (right) == 0)
944 werror (E_DIVIDE_BY_ZERO);
949 retval = operandFromValue (valCastLiteral (type,
950 operandLitValue (left) /
951 operandLitValue (right)));
954 if ((unsigned long) operandLitValue (right) == 0) {
955 werror (E_DIVIDE_BY_ZERO);
959 retval = operandFromLit ((SPEC_USIGN(let) ?
960 (unsigned long) operandLitValue (left) :
961 (long) operandLitValue (left)) %
963 (unsigned long) operandLitValue (right) :
964 (long) operandLitValue (right)));
968 retval = operandFromLit (((SPEC_USIGN(let) ?
969 (unsigned long) operandLitValue (left) :
970 (long) operandLitValue (left)) <<
972 (unsigned long) operandLitValue (right) :
973 (long) operandLitValue (right))));
976 retval = operandFromLit (((SPEC_USIGN(let) ?
977 (unsigned long) operandLitValue (left) :
978 (long) operandLitValue (left)) >>
980 (unsigned long) operandLitValue (right) :
981 (long) operandLitValue (right))));
984 retval = operandFromLit (operandLitValue (left) ==
985 operandLitValue (right));
988 retval = operandFromLit (operandLitValue (left) <
989 operandLitValue (right));
992 retval = operandFromLit (operandLitValue (left) <=
993 operandLitValue (right));
996 retval = operandFromLit (operandLitValue (left) !=
997 operandLitValue (right));
1000 retval = operandFromLit (operandLitValue (left) >
1001 operandLitValue (right));
1004 retval = operandFromLit (operandLitValue (left) >=
1005 operandLitValue (right));
1008 retval = operandFromLit ((unsigned long) operandLitValue (left) &
1009 (unsigned long) operandLitValue (right));
1012 retval = operandFromLit ((unsigned long) operandLitValue (left) |
1013 (unsigned long) operandLitValue (right));
1016 retval = operandFromLit ((unsigned long) operandLitValue (left) ^
1017 (unsigned long) operandLitValue (right));
1020 retval = operandFromLit (operandLitValue (left) &&
1021 operandLitValue (right));
1024 retval = operandFromLit (operandLitValue (left) ||
1025 operandLitValue (right));
1029 long i = (long) operandLitValue (left);
1031 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1037 long i = (long) operandLitValue (left);
1039 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1045 retval = operandFromLit (-1 * operandLitValue (left));
1049 retval = operandFromLit (~((long) operandLitValue (left)));
1053 retval = operandFromLit (!operandLitValue (left));
1057 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1058 " operandOperation invalid operator ");
1066 /*-----------------------------------------------------------------*/
1067 /* isOperandEqual - compares two operand & return 1 if they r = */
1068 /*-----------------------------------------------------------------*/
1070 isOperandEqual (operand * left, operand * right)
1072 /* if the pointers are equal then they are equal */
1076 /* if either of them null then false */
1077 if (!left || !right)
1080 if (left->type != right->type)
1083 if (IS_SYMOP (left) && IS_SYMOP (right))
1084 return left->key == right->key;
1086 /* if types are the same */
1090 return isSymbolEqual (left->operand.symOperand,
1091 right->operand.symOperand);
1093 return (floatFromVal (left->operand.valOperand) ==
1094 floatFromVal (right->operand.valOperand));
1096 if (compareType (left->operand.typeOperand,
1097 right->operand.typeOperand) == 1)
1104 /*-----------------------------------------------------------------*/
1105 /* isiCodeEqual - comapres two iCodes are returns true if yes */
1106 /*-----------------------------------------------------------------*/
1108 isiCodeEqual (iCode * left, iCode * right)
1110 /* if the same pointer */
1114 /* if either of them null */
1115 if (!left || !right)
1118 /* if operand are the same */
1119 if (left->op == right->op)
1122 /* compare all the elements depending on type */
1123 if (left->op != IFX)
1125 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1127 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1133 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1135 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1137 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1145 /*-----------------------------------------------------------------*/
1146 /* newiTempFromOp - create a temp Operand with same attributes */
1147 /*-----------------------------------------------------------------*/
1149 newiTempFromOp (operand * op)
1159 nop = newiTempOperand (operandType (op), TRUE);
1160 nop->isaddr = op->isaddr;
1161 nop->isvolatile = op->isvolatile;
1162 nop->isGlobal = op->isGlobal;
1163 nop->isLiteral = op->isLiteral;
1164 nop->usesDefs = op->usesDefs;
1165 nop->isParm = op->isParm;
1169 /*-----------------------------------------------------------------*/
1170 /* operand from operand - creates an operand holder for the type */
1171 /*-----------------------------------------------------------------*/
1173 operandFromOperand (operand * op)
1179 nop = newOperand ();
1180 nop->type = op->type;
1181 nop->isaddr = op->isaddr;
1183 nop->isvolatile = op->isvolatile;
1184 nop->isGlobal = op->isGlobal;
1185 nop->isLiteral = op->isLiteral;
1186 nop->usesDefs = op->usesDefs;
1187 nop->isParm = op->isParm;
1192 nop->operand.symOperand = op->operand.symOperand;
1195 nop->operand.valOperand = op->operand.valOperand;
1198 nop->operand.typeOperand = op->operand.typeOperand;
1205 /*-----------------------------------------------------------------*/
1206 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1207 /*-----------------------------------------------------------------*/
1209 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1211 operand *nop = operandFromOperand (op);
1213 if (nop->type == SYMBOL)
1215 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1216 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1222 /*-----------------------------------------------------------------*/
1223 /* operandFromSymbol - creates an operand from a symbol */
1224 /*-----------------------------------------------------------------*/
1226 operandFromSymbol (symbol * sym)
1231 /* if the symbol's type is a literal */
1232 /* then it is an enumerator type */
1233 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1234 return operandFromValue (valFromType (sym->etype));
1237 sym->key = ++operandKey;
1239 /* if this an implicit variable, means struct/union */
1240 /* member so just return it */
1241 if (sym->implicit || IS_FUNC (sym->type))
1245 op->operand.symOperand = sym;
1247 op->isvolatile = isOperandVolatile (op, TRUE);
1248 op->isGlobal = isOperandGlobal (op);
1252 /* under the following conditions create a
1253 register equivalent for a local symbol */
1254 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1255 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1256 /* (!TARGET_IS_DS390)) && */
1257 (!(options.model == MODEL_FLAT24)) ) &&
1258 options.stackAuto == 0)
1261 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1262 !IS_FUNC (sym->type) && /* not a function */
1263 !sym->_isparm && /* not a parameter */
1264 sym->level && /* is a local variable */
1265 !sym->addrtaken && /* whose address has not been taken */
1266 !sym->reqv && /* does not already have a register euivalence */
1267 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1268 !IS_STATIC (sym->etype) && /* and not declared static */
1269 !sym->islbl && /* not a label */
1270 ok && /* farspace check */
1271 !IS_BITVAR (sym->etype) /* not a bit variable */
1275 /* we will use it after all optimizations
1276 and before liveRange calculation */
1277 sym->reqv = newiTempOperand (sym->type, 0);
1278 sym->reqv->key = sym->key;
1279 OP_SYMBOL (sym->reqv)->key = sym->key;
1280 OP_SYMBOL (sym->reqv)->isreqv = 1;
1281 OP_SYMBOL (sym->reqv)->islocal = 1;
1282 SPIL_LOC (sym->reqv) = sym;
1285 if (!IS_AGGREGATE (sym->type))
1289 op->operand.symOperand = sym;
1292 op->isvolatile = isOperandVolatile (op, TRUE);
1293 op->isGlobal = isOperandGlobal (op);
1294 op->isPtr = IS_PTR (operandType (op));
1295 op->isParm = sym->_isparm;
1300 /* itemp = &[_symbol] */
1302 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1303 IC_LEFT (ic)->type = SYMBOL;
1304 IC_LEFT (ic)->operand.symOperand = sym;
1305 IC_LEFT (ic)->key = sym->key;
1306 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1307 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1308 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1311 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1312 if (IS_ARRAY (sym->type))
1314 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1315 IC_RESULT (ic)->isaddr = 0;
1318 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1320 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1324 return IC_RESULT (ic);
1327 /*-----------------------------------------------------------------*/
1328 /* operandFromValue - creates an operand from value */
1329 /*-----------------------------------------------------------------*/
1331 operandFromValue (value * val)
1335 /* if this is a symbol then do the symbol thing */
1337 return operandFromSymbol (val->sym);
1339 /* this is not a symbol */
1342 op->operand.valOperand = val;
1343 op->isLiteral = isOperandLiteral (op);
1347 /*-----------------------------------------------------------------*/
1348 /* operandFromLink - operand from typeChain */
1349 /*-----------------------------------------------------------------*/
1351 operandFromLink (sym_link * type)
1355 /* operand from sym_link */
1361 op->operand.typeOperand = copyLinkChain (type);
1365 /*-----------------------------------------------------------------*/
1366 /* operandFromLit - makes an operand from a literal value */
1367 /*-----------------------------------------------------------------*/
1369 operandFromLit (double i)
1371 return operandFromValue (valueFromLit (i));
1374 /*-----------------------------------------------------------------*/
1375 /* operandFromAst - creates an operand from an ast */
1376 /*-----------------------------------------------------------------*/
1378 operandFromAst (ast * tree,int lvl)
1384 /* depending on type do */
1388 return ast2iCode (tree,lvl+1);
1392 return operandFromValue (tree->opval.val);
1396 return operandFromLink (tree->opval.lnk);
1400 /* Just to keep the comiler happy */
1401 return (operand *) 0;
1404 /*-----------------------------------------------------------------*/
1405 /* setOperandType - sets the operand's type to the given type */
1406 /*-----------------------------------------------------------------*/
1408 setOperandType (operand * op, sym_link * type)
1410 /* depending on the type of operand */
1415 op->operand.valOperand->etype =
1416 getSpec (op->operand.valOperand->type =
1417 copyLinkChain (type));
1421 if (op->operand.symOperand->isitmp)
1422 op->operand.symOperand->etype =
1423 getSpec (op->operand.symOperand->type =
1424 copyLinkChain (type));
1426 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1427 "attempt to modify type of source");
1431 op->operand.typeOperand = copyLinkChain (type);
1436 /*-----------------------------------------------------------------*/
1437 /* Get size in byte of ptr need to access an array */
1438 /*-----------------------------------------------------------------*/
1440 getArraySizePtr (operand * op)
1442 sym_link *ltype = operandType(op);
1446 int size = getSize(ltype);
1447 return(IS_GENPTR(ltype)?(size-1):size);
1452 sym_link *letype = getSpec(ltype);
1453 switch (PTR_TYPE (SPEC_OCLS (letype)))
1465 return (GPTRSIZE-1);
1474 /*-----------------------------------------------------------------*/
1475 /* perform "usual unary conversions" */
1476 /*-----------------------------------------------------------------*/
1478 usualUnaryConversions (operand * op)
1480 if (IS_INTEGRAL (operandType (op)))
1482 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1485 return geniCodeCast (INTTYPE, op, TRUE);
1491 /*-----------------------------------------------------------------*/
1492 /* perform "usual binary conversions" */
1493 /*-----------------------------------------------------------------*/
1495 usualBinaryConversions (operand ** op1, operand ** op2)
1498 sym_link *rtype = operandType (*op2);
1499 sym_link *ltype = operandType (*op1);
1501 ctype = computeType (ltype, rtype);
1502 *op1 = geniCodeCast (ctype, *op1, TRUE);
1503 *op2 = geniCodeCast (ctype, *op2, TRUE);
1508 /*-----------------------------------------------------------------*/
1509 /* geniCodeValueAtAddress - generate intermeditate code for value */
1511 /*-----------------------------------------------------------------*/
1513 geniCodeRValue (operand * op, bool force)
1516 sym_link *type = operandType (op);
1517 sym_link *etype = getSpec (type);
1519 /* if this is an array & already */
1520 /* an address then return this */
1521 if (IS_AGGREGATE (type) ||
1522 (IS_PTR (type) && !force && !op->isaddr))
1523 return operandFromOperand (op);
1525 /* if this is not an address then must be */
1526 /* rvalue already so return this one */
1530 /* if this is not a temp symbol then */
1531 if (!IS_ITEMP (op) &&
1533 !IN_FARSPACE (SPEC_OCLS (etype)))
1535 op = operandFromOperand (op);
1540 if (IS_SPEC (type) &&
1541 IS_TRUE_SYMOP (op) &&
1542 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1543 /* TARGET_IS_DS390)) */
1544 (options.model == MODEL_FLAT24) ))
1546 op = operandFromOperand (op);
1551 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1552 if (IS_PTR (type) && op->isaddr && force)
1555 type = copyLinkChain (type);
1557 IC_RESULT (ic) = newiTempOperand (type, 1);
1558 IC_RESULT (ic)->isaddr = 0;
1560 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1562 /* if the right is a symbol */
1563 if (op->type == SYMBOL)
1564 IC_RESULT (ic)->operand.symOperand->args =
1565 op->operand.symOperand->args;
1568 return IC_RESULT (ic);
1571 /*-----------------------------------------------------------------*/
1572 /* geniCodeCast - changes the value from one type to another */
1573 /*-----------------------------------------------------------------*/
1575 geniCodeCast (sym_link * type, operand * op, bool implicit)
1579 sym_link *opetype = getSpec (optype = operandType (op));
1582 /* one of them has size zero then error */
1583 if (IS_VOID (optype))
1585 werror (E_CAST_ZERO);
1589 /* if the operand is already the desired type then do nothing */
1590 if (compareType (type, optype) == 1)
1593 /* if this is a literal then just change the type & return */
1594 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1595 return operandFromValue (valCastLiteral (type,
1596 operandLitValue (op)));
1599 /* if casting to/from pointers, do some checking */
1600 if (IS_PTR(type)) { // to a pointer
1601 if (!IS_PTR(optype)) { // from a non pointer
1602 if (IS_INTEGRAL(optype)) {
1603 // maybe this is NULL, than it's ok.
1604 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1605 if (IS_GENPTR(type)) {
1606 // no way to set the storage
1607 if (IS_LITERAL(optype)) {
1608 werror(E_LITERAL_GENERIC);
1610 werror(E_NONPTR2_GENPTR);
1612 } else if (implicit) {
1613 werror(W_INTEGRAL2PTR_NOCAST);
1616 } else { // shouldn't do that with float, array or structure
1617 werror(E_INCOMPAT_TYPES);
1619 } else { // from a pointer to a pointer
1620 if (implicit) { // if not to generic, they have to match
1621 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1622 werror(E_INCOMPAT_PTYPES);
1626 } else { // to a non pointer
1627 if (IS_PTR(optype)) { // from a pointer
1628 if (implicit) { // sneaky
1629 if (IS_INTEGRAL(type)) {
1630 werror(W_PTR2INTEGRAL_NOCAST);
1631 } else { // shouldn't do that with float, array or structure
1632 werror(E_INCOMPAT_TYPES);
1638 /* if they are the same size create an assignment */
1639 if (getSize (type) == getSize (optype) &&
1640 !IS_BITFIELD (type) &&
1642 !IS_FLOAT (optype) &&
1643 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1644 (!IS_SPEC (type) && !IS_SPEC (optype))))
1647 ic = newiCode ('=', NULL, op);
1648 IC_RESULT (ic) = newiTempOperand (type, 0);
1649 SPIL_LOC (IC_RESULT (ic)) =
1650 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1651 IC_RESULT (ic)->isaddr = 0;
1655 ic = newiCode (CAST, operandFromLink (type),
1656 geniCodeRValue (op, FALSE));
1658 IC_RESULT (ic) = newiTempOperand (type, 0);
1661 /* preserve the storage class & output class */
1662 /* of the original variable */
1663 restype = getSpec (operandType (IC_RESULT (ic)));
1664 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1665 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1668 return IC_RESULT (ic);
1671 /*-----------------------------------------------------------------*/
1672 /* geniCodeLabel - will create a Label */
1673 /*-----------------------------------------------------------------*/
1675 geniCodeLabel (symbol * label)
1679 ic = newiCodeLabelGoto (LABEL, label);
1683 /*-----------------------------------------------------------------*/
1684 /* geniCodeGoto - will create a Goto */
1685 /*-----------------------------------------------------------------*/
1687 geniCodeGoto (symbol * label)
1691 ic = newiCodeLabelGoto (GOTO, label);
1695 /*-----------------------------------------------------------------*/
1696 /* geniCodeMultiply - gen intermediate code for multiplication */
1697 /*-----------------------------------------------------------------*/
1699 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1706 /* if they are both literal then we know the result */
1707 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1708 return operandFromValue (valMult (left->operand.valOperand,
1709 right->operand.valOperand));
1711 if (IS_LITERAL(retype)) {
1712 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1715 resType = usualBinaryConversions (&left, &right);
1717 rtype = operandType (right);
1718 retype = getSpec (rtype);
1719 ltype = operandType (left);
1720 letype = getSpec (ltype);
1724 SPEC_NOUN(getSpec(resType))=V_INT;
1727 /* if the right is a literal & power of 2 */
1728 /* then make it a left shift */
1729 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1730 efficient in most cases than 2 bytes result = 2 bytes << literal
1731 if port has 1 byte muldiv */
1732 if (p2 && !IS_FLOAT (letype) &&
1733 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1734 (port->support.muldiv == 1)))
1736 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1738 /* LEFT_OP need same size for left and result, */
1739 left = geniCodeCast (resType, left, TRUE);
1740 ltype = operandType (left);
1742 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1746 ic = newiCode ('*', left, right); /* normal multiplication */
1747 /* if the size left or right > 1 then support routine */
1748 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1752 IC_RESULT (ic) = newiTempOperand (resType, 1);
1755 return IC_RESULT (ic);
1758 /*-----------------------------------------------------------------*/
1759 /* geniCodeDivision - gen intermediate code for division */
1760 /*-----------------------------------------------------------------*/
1762 geniCodeDivision (operand * left, operand * right)
1767 sym_link *rtype = operandType (right);
1768 sym_link *retype = getSpec (rtype);
1769 sym_link *ltype = operandType (left);
1770 sym_link *letype = getSpec (ltype);
1772 resType = usualBinaryConversions (&left, &right);
1774 /* if the right is a literal & power of 2 */
1775 /* then make it a right shift */
1776 if (IS_LITERAL (retype) &&
1777 !IS_FLOAT (letype) &&
1778 (p2 = powof2 ((unsigned long)
1779 floatFromVal (right->operand.valOperand)))) {
1780 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1784 ic = newiCode ('/', left, right); /* normal division */
1785 /* if the size left or right > 1 then support routine */
1786 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1789 IC_RESULT (ic) = newiTempOperand (resType, 0);
1792 return IC_RESULT (ic);
1794 /*-----------------------------------------------------------------*/
1795 /* geniCodeModulus - gen intermediate code for modulus */
1796 /*-----------------------------------------------------------------*/
1798 geniCodeModulus (operand * left, operand * right)
1804 /* if they are both literal then we know the result */
1805 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1806 return operandFromValue (valMod (left->operand.valOperand,
1807 right->operand.valOperand));
1809 resType = usualBinaryConversions (&left, &right);
1811 /* now they are the same size */
1812 ic = newiCode ('%', left, right);
1814 /* if the size left or right > 1 then support routine */
1815 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1817 IC_RESULT (ic) = newiTempOperand (resType, 0);
1820 return IC_RESULT (ic);
1823 /*-----------------------------------------------------------------*/
1824 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1825 /*-----------------------------------------------------------------*/
1827 geniCodePtrPtrSubtract (operand * left, operand * right)
1833 /* if they are both literals then */
1834 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1836 result = operandFromValue (valMinus (left->operand.valOperand,
1837 right->operand.valOperand));
1841 ic = newiCode ('-', left, right);
1843 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1847 return geniCodeDivision (result,
1848 operandFromLit (getSize (ltype->next)));
1851 /*-----------------------------------------------------------------*/
1852 /* geniCodeSubtract - generates code for subtraction */
1853 /*-----------------------------------------------------------------*/
1855 geniCodeSubtract (operand * left, operand * right)
1862 /* if they both pointers then */
1863 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1864 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1865 return geniCodePtrPtrSubtract (left, right);
1867 /* if they are both literal then we know the result */
1868 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1869 && left->isLiteral && right->isLiteral)
1870 return operandFromValue (valMinus (left->operand.valOperand,
1871 right->operand.valOperand));
1873 /* if left is an array or pointer */
1874 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1876 isarray = left->isaddr;
1877 right = geniCodeMultiply (right,
1878 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1879 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1882 { /* make them the same size */
1883 resType = usualBinaryConversions (&left, &right);
1886 ic = newiCode ('-', left, right);
1888 IC_RESULT (ic) = newiTempOperand (resType, 1);
1889 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1891 /* if left or right is a float */
1892 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1896 return IC_RESULT (ic);
1899 /*-----------------------------------------------------------------*/
1900 /* geniCodeAdd - generates iCode for addition */
1901 /*-----------------------------------------------------------------*/
1903 geniCodeAdd (operand * left, operand * right,int lvl)
1911 /* if left is an array then array access */
1912 if (IS_ARRAY (ltype))
1913 return geniCodeArray (left, right,lvl);
1915 /* if the right side is LITERAL zero */
1916 /* return the left side */
1917 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1920 /* if left is literal zero return right */
1921 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1924 /* if left is an array or pointer then size */
1927 isarray = left->isaddr;
1928 // there is no need to multiply with 1
1929 if (getSize(ltype->next)!=1) {
1930 size = operandFromLit (getSize (ltype->next));
1931 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1933 resType = copyLinkChain (ltype);
1936 { /* make them the same size */
1937 resType = usualBinaryConversions (&left, &right);
1940 /* if they are both literals then we know */
1941 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1942 && left->isLiteral && right->isLiteral)
1943 return operandFromValue (valPlus (valFromType (letype),
1944 valFromType (retype)));
1946 ic = newiCode ('+', left, right);
1948 IC_RESULT (ic) = newiTempOperand (resType, 1);
1949 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1951 /* if left or right is a float then support
1953 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1958 return IC_RESULT (ic);
1962 /*-----------------------------------------------------------------*/
1963 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1964 /*-----------------------------------------------------------------*/
1966 aggrToPtr (sym_link * type, bool force)
1972 if (IS_PTR (type) && !force)
1975 etype = getSpec (type);
1979 /* if the output class is generic */
1980 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1981 DCL_PTR_CONST (ptype) = port->mem.code_ro;
1983 /* if the variable was declared a constant */
1984 /* then the pointer points to a constant */
1985 if (IS_CONSTANT (etype))
1986 DCL_PTR_CONST (ptype) = 1;
1988 /* the variable was volatile then pointer to volatile */
1989 if (IS_VOLATILE (etype))
1990 DCL_PTR_VOLATILE (ptype) = 1;
1994 /*-----------------------------------------------------------------*/
1995 /* geniCodeArray2Ptr - array to pointer */
1996 /*-----------------------------------------------------------------*/
1998 geniCodeArray2Ptr (operand * op)
2000 sym_link *optype = operandType (op);
2001 sym_link *opetype = getSpec (optype);
2003 /* set the pointer depending on the storage class */
2004 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2005 DCL_PTR_CONST (optype) = port->mem.code_ro;
2008 /* if the variable was declared a constant */
2009 /* then the pointer points to a constant */
2010 if (IS_CONSTANT (opetype))
2011 DCL_PTR_CONST (optype) = 1;
2013 /* the variable was volatile then pointer to volatile */
2014 if (IS_VOLATILE (opetype))
2015 DCL_PTR_VOLATILE (optype) = 1;
2021 /*-----------------------------------------------------------------*/
2022 /* geniCodeArray - array access */
2023 /*-----------------------------------------------------------------*/
2025 geniCodeArray (operand * left, operand * right,int lvl)
2028 sym_link *ltype = operandType (left);
2032 if (IS_PTR (ltype->next) && left->isaddr)
2034 left = geniCodeRValue (left, FALSE);
2036 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2039 right = geniCodeMultiply (right,
2040 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2042 /* we can check for limits here */
2043 if (isOperandLiteral (right) &&
2046 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2048 werror (E_ARRAY_BOUND);
2049 right = operandFromLit (0);
2052 ic = newiCode ('+', left, right);
2054 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2055 !IS_AGGREGATE (ltype->next) &&
2056 !IS_PTR (ltype->next))
2057 ? ltype : ltype->next), 0);
2059 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2061 return IC_RESULT (ic);
2064 /*-----------------------------------------------------------------*/
2065 /* geniCodeStruct - generates intermediate code for structres */
2066 /*-----------------------------------------------------------------*/
2068 geniCodeStruct (operand * left, operand * right, bool islval)
2071 sym_link *type = operandType (left);
2072 sym_link *etype = getSpec (type);
2074 symbol *element = getStructElement (SPEC_STRUCT (etype),
2075 right->operand.symOperand);
2077 /* add the offset */
2078 ic = newiCode ('+', left, operandFromLit (element->offset));
2080 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2082 /* preserve the storage & output class of the struct */
2083 /* as well as the volatile attribute */
2084 retype = getSpec (operandType (IC_RESULT (ic)));
2085 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2086 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2087 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2089 if (IS_PTR (element->type))
2090 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2092 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2096 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2099 /*-----------------------------------------------------------------*/
2100 /* geniCodePostInc - generate int code for Post increment */
2101 /*-----------------------------------------------------------------*/
2103 geniCodePostInc (operand * op)
2107 sym_link *optype = operandType (op);
2109 operand *rv = (IS_ITEMP (op) ?
2110 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2112 sym_link *rvtype = operandType (rv);
2115 /* if this is not an address we have trouble */
2118 werror (E_LVALUE_REQUIRED, "++");
2122 rOp = newiTempOperand (rvtype, 0);
2123 OP_SYMBOL(rOp)->noSpilLoc = 1;
2126 OP_SYMBOL(rv)->noSpilLoc = 1;
2128 geniCodeAssign (rOp, rv, 0);
2130 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2131 if (IS_FLOAT (rvtype))
2132 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2134 ic = newiCode ('+', rv, operandFromLit (size));
2136 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2139 geniCodeAssign (op, result, 0);
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodePreInc - generate code for preIncrement */
2147 /*-----------------------------------------------------------------*/
2149 geniCodePreInc (operand * op)
2152 sym_link *optype = operandType (op);
2153 operand *rop = (IS_ITEMP (op) ?
2154 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2156 sym_link *roptype = operandType (rop);
2162 werror (E_LVALUE_REQUIRED, "++");
2167 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2168 if (IS_FLOAT (roptype))
2169 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2171 ic = newiCode ('+', rop, operandFromLit (size));
2172 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2176 return geniCodeAssign (op, result, 0);
2179 /*-----------------------------------------------------------------*/
2180 /* geniCodePostDec - generates code for Post decrement */
2181 /*-----------------------------------------------------------------*/
2183 geniCodePostDec (operand * op)
2187 sym_link *optype = operandType (op);
2189 operand *rv = (IS_ITEMP (op) ?
2190 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2192 sym_link *rvtype = operandType (rv);
2195 /* if this is not an address we have trouble */
2198 werror (E_LVALUE_REQUIRED, "--");
2202 rOp = newiTempOperand (rvtype, 0);
2203 OP_SYMBOL(rOp)->noSpilLoc = 1;
2206 OP_SYMBOL(rv)->noSpilLoc = 1;
2208 geniCodeAssign (rOp, rv, 0);
2210 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2211 if (IS_FLOAT (rvtype))
2212 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2214 ic = newiCode ('-', rv, operandFromLit (size));
2216 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2219 geniCodeAssign (op, result, 0);
2225 /*-----------------------------------------------------------------*/
2226 /* geniCodePreDec - generate code for pre decrement */
2227 /*-----------------------------------------------------------------*/
2229 geniCodePreDec (operand * op)
2232 sym_link *optype = operandType (op);
2233 operand *rop = (IS_ITEMP (op) ?
2234 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2236 sym_link *roptype = operandType (rop);
2242 werror (E_LVALUE_REQUIRED, "--");
2247 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2248 if (IS_FLOAT (roptype))
2249 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2251 ic = newiCode ('-', rop, operandFromLit (size));
2252 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2256 return geniCodeAssign (op, result, 0);
2260 /*-----------------------------------------------------------------*/
2261 /* geniCodeBitwise - gen int code for bitWise operators */
2262 /*-----------------------------------------------------------------*/
2264 geniCodeBitwise (operand * left, operand * right,
2265 int oper, sym_link * resType)
2269 left = geniCodeCast (resType, left, TRUE);
2270 right = geniCodeCast (resType, right, TRUE);
2272 ic = newiCode (oper, left, right);
2273 IC_RESULT (ic) = newiTempOperand (resType, 0);
2276 return IC_RESULT (ic);
2279 /*-----------------------------------------------------------------*/
2280 /* geniCodeAddressOf - gens icode for '&' address of operator */
2281 /*-----------------------------------------------------------------*/
2283 geniCodeAddressOf (operand * op)
2287 sym_link *optype = operandType (op);
2288 sym_link *opetype = getSpec (optype);
2290 /* lvalue check already done in decorateType */
2291 /* this must be a lvalue */
2292 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2293 /* werror (E_LVALUE_REQUIRED,"&"); */
2298 p->class = DECLARATOR;
2300 /* set the pointer depending on the storage class */
2301 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2302 DCL_PTR_CONST (p) = port->mem.code_ro;
2304 /* make sure we preserve the const & volatile */
2305 if (IS_CONSTANT (opetype))
2306 DCL_PTR_CONST (p) = 1;
2308 if (IS_VOLATILE (opetype))
2309 DCL_PTR_VOLATILE (p) = 1;
2311 p->next = copyLinkChain (optype);
2313 /* if already a temp */
2316 setOperandType (op, p);
2321 /* other wise make this of the type coming in */
2322 ic = newiCode (ADDRESS_OF, op, NULL);
2323 IC_RESULT (ic) = newiTempOperand (p, 1);
2324 IC_RESULT (ic)->isaddr = 0;
2326 return IC_RESULT (ic);
2328 /*-----------------------------------------------------------------*/
2329 /* setOClass - sets the output class depending on the pointer type */
2330 /*-----------------------------------------------------------------*/
2332 setOClass (sym_link * ptr, sym_link * spec)
2334 switch (DCL_TYPE (ptr))
2337 SPEC_OCLS (spec) = data;
2341 SPEC_OCLS (spec) = generic;
2345 SPEC_OCLS (spec) = xdata;
2349 SPEC_OCLS (spec) = code;
2353 SPEC_OCLS (spec) = idata;
2357 SPEC_OCLS (spec) = xstack;
2361 SPEC_OCLS (spec) = eeprom;
2370 /*-----------------------------------------------------------------*/
2371 /* geniCodeDerefPtr - dereference pointer with '*' */
2372 /*-----------------------------------------------------------------*/
2374 geniCodeDerefPtr (operand * op,int lvl)
2376 sym_link *rtype, *retype;
2377 sym_link *optype = operandType (op);
2379 /* if this is a pointer then generate the rvalue */
2380 if (IS_PTR (optype))
2382 if (IS_TRUE_SYMOP (op))
2385 op = geniCodeRValue (op, TRUE);
2388 op = geniCodeRValue (op, TRUE);
2391 /* now get rid of the pointer part */
2392 if (isLvaluereq(lvl) && IS_ITEMP (op))
2394 retype = getSpec (rtype = copyLinkChain (optype));
2398 retype = getSpec (rtype = copyLinkChain (optype->next));
2401 /* if this is a pointer then outputclass needs 2b updated */
2402 if (IS_PTR (optype))
2403 setOClass (optype, retype);
2405 op->isGptr = IS_GENPTR (optype);
2407 /* if the pointer was declared as a constant */
2408 /* then we cannot allow assignment to the derefed */
2409 if (IS_PTR_CONST (optype))
2410 SPEC_CONST (retype) = 1;
2412 op->isaddr = (IS_PTR (rtype) ||
2413 IS_STRUCT (rtype) ||
2418 if (!isLvaluereq(lvl))
2419 op = geniCodeRValue (op, TRUE);
2421 setOperandType (op, rtype);
2426 /*-----------------------------------------------------------------*/
2427 /* geniCodeUnaryMinus - does a unary minus of the operand */
2428 /*-----------------------------------------------------------------*/
2430 geniCodeUnaryMinus (operand * op)
2433 sym_link *optype = operandType (op);
2435 if (IS_LITERAL (optype))
2436 return operandFromLit (-floatFromVal (op->operand.valOperand));
2438 ic = newiCode (UNARYMINUS, op, NULL);
2439 IC_RESULT (ic) = newiTempOperand (optype, 0);
2441 return IC_RESULT (ic);
2444 /*-----------------------------------------------------------------*/
2445 /* geniCodeLeftShift - gen i code for left shift */
2446 /*-----------------------------------------------------------------*/
2448 geniCodeLeftShift (operand * left, operand * right)
2452 ic = newiCode (LEFT_OP, left, right);
2453 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2455 return IC_RESULT (ic);
2458 /*-----------------------------------------------------------------*/
2459 /* geniCodeRightShift - gen i code for right shift */
2460 /*-----------------------------------------------------------------*/
2462 geniCodeRightShift (operand * left, operand * right)
2466 ic = newiCode (RIGHT_OP, left, right);
2467 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2469 return IC_RESULT (ic);
2472 /*-----------------------------------------------------------------*/
2473 /* geniCodeLogic- logic code */
2474 /*-----------------------------------------------------------------*/
2476 geniCodeLogic (operand * left, operand * right, int op)
2480 sym_link *rtype = operandType (right);
2481 sym_link *ltype = operandType (left);
2483 /* left is integral type and right is literal then
2484 check if the literal value is within bounds */
2485 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2487 checkConstantRange(ltype,
2488 operandLitValue(right), "compare operation", 1);
2491 ctype = usualBinaryConversions (&left, &right);
2493 ic = newiCode (op, left, right);
2494 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2496 /* if comparing float
2497 and not a '==' || '!=' || '&&' || '||' (these
2499 if (IS_FLOAT(ctype) &&
2507 return IC_RESULT (ic);
2510 /*-----------------------------------------------------------------*/
2511 /* geniCodeUnary - for a a generic unary operation */
2512 /*-----------------------------------------------------------------*/
2514 geniCodeUnary (operand * op, int oper)
2516 iCode *ic = newiCode (oper, op, NULL);
2518 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2520 return IC_RESULT (ic);
2523 /*-----------------------------------------------------------------*/
2524 /* geniCodeConditional - geniCode for '?' ':' operation */
2525 /*-----------------------------------------------------------------*/
2527 geniCodeConditional (ast * tree,int lvl)
2530 symbol *falseLabel = newiTempLabel (NULL);
2531 symbol *exitLabel = newiTempLabel (NULL);
2532 operand *cond = ast2iCode (tree->left,lvl+1);
2533 operand *true, *false, *result;
2535 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2539 true = ast2iCode (tree->right->left,lvl+1);
2541 /* move the value to a new Operand */
2542 result = newiTempOperand (operandType (true), 0);
2543 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2545 /* generate an unconditional goto */
2546 geniCodeGoto (exitLabel);
2548 /* now for the right side */
2549 geniCodeLabel (falseLabel);
2551 false = ast2iCode (tree->right->right,lvl+1);
2552 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2554 /* create the exit label */
2555 geniCodeLabel (exitLabel);
2560 /*-----------------------------------------------------------------*/
2561 /* geniCodeAssign - generate code for assignment */
2562 /*-----------------------------------------------------------------*/
2564 geniCodeAssign (operand * left, operand * right, int nosupdate)
2567 sym_link *ltype = operandType (left);
2568 sym_link *rtype = operandType (right);
2570 if (!left->isaddr && !IS_ITEMP (left))
2572 werror (E_LVALUE_REQUIRED, "assignment");
2576 /* left is integral type and right is literal then
2577 check if the literal value is within bounds */
2578 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2580 checkConstantRange(ltype,
2581 operandLitValue(right), "= operation", 0);
2584 /* if the left & right type don't exactly match */
2585 /* if pointer set then make sure the check is
2586 done with the type & not the pointer */
2587 /* then cast rights type to left */
2589 /* first check the type for pointer assignement */
2590 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2591 compareType (ltype, rtype) < 0)
2593 if (compareType (ltype->next, rtype) < 0)
2594 right = geniCodeCast (ltype->next, right, TRUE);
2596 else if (compareType (ltype, rtype) < 0)
2597 right = geniCodeCast (ltype, right, TRUE);
2599 /* if left is a true symbol & ! volatile
2600 create an assignment to temporary for
2601 the right & then assign this temporary
2602 to the symbol this is SSA . isn't it simple
2603 and folks have published mountains of paper on it */
2604 if (IS_TRUE_SYMOP (left) &&
2605 !isOperandVolatile (left, FALSE) &&
2606 isOperandGlobal (left))
2610 if (IS_TRUE_SYMOP (right))
2611 sym = OP_SYMBOL (right);
2612 ic = newiCode ('=', NULL, right);
2613 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2614 SPIL_LOC (right) = sym;
2618 ic = newiCode ('=', NULL, right);
2619 IC_RESULT (ic) = left;
2622 /* if left isgptr flag is set then support
2623 routine will be required */
2627 ic->nosupdate = nosupdate;
2631 /*-----------------------------------------------------------------*/
2632 /* geniCodeSEParms - generate code for side effecting fcalls */
2633 /*-----------------------------------------------------------------*/
2635 geniCodeSEParms (ast * parms,int lvl)
2640 if (parms->type == EX_OP && parms->opval.op == PARAM)
2642 geniCodeSEParms (parms->left,lvl);
2643 geniCodeSEParms (parms->right,lvl);
2647 /* hack don't like this but too lazy to think of
2649 if (IS_ADDRESS_OF_OP (parms))
2650 parms->left->lvalue = 1;
2652 if (IS_CAST_OP (parms) &&
2653 IS_PTR (parms->ftype) &&
2654 IS_ADDRESS_OF_OP (parms->right))
2655 parms->right->left->lvalue = 1;
2657 parms->opval.oprnd =
2658 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2660 parms->type = EX_OPERAND;
2663 /*-----------------------------------------------------------------*/
2664 /* geniCodeParms - generates parameters */
2665 /*-----------------------------------------------------------------*/
2667 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2675 /* if this is a param node then do the left & right */
2676 if (parms->type == EX_OP && parms->opval.op == PARAM)
2678 geniCodeParms (parms->left, stack, fetype, func,lvl);
2679 geniCodeParms (parms->right, stack, fetype, func,lvl);
2683 /* get the parameter value */
2684 if (parms->type == EX_OPERAND)
2685 pval = parms->opval.oprnd;
2688 /* maybe this else should go away ?? */
2689 /* hack don't like this but too lazy to think of
2691 if (IS_ADDRESS_OF_OP (parms))
2692 parms->left->lvalue = 1;
2694 if (IS_CAST_OP (parms) &&
2695 IS_PTR (parms->ftype) &&
2696 IS_ADDRESS_OF_OP (parms->right))
2697 parms->right->left->lvalue = 1;
2699 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2702 /* if register parm then make it a send */
2703 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2704 IS_REGPARM (parms->etype)) && !func->hasVargs)
2706 ic = newiCode (SEND, pval, NULL);
2711 /* now decide whether to push or assign */
2712 if (!(options.stackAuto || IS_RENT (fetype)))
2716 operand *top = operandFromSymbol (parms->argSym);
2717 geniCodeAssign (top, pval, 1);
2721 sym_link *p = operandType (pval);
2723 ic = newiCode (IPUSH, pval, NULL);
2725 /* update the stack adjustment */
2726 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2733 /*-----------------------------------------------------------------*/
2734 /* geniCodeCall - generates temp code for calling */
2735 /*-----------------------------------------------------------------*/
2737 geniCodeCall (operand * left, ast * parms,int lvl)
2741 sym_link *type, *etype;
2744 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2745 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2746 werror (E_FUNCTION_EXPECTED);
2750 /* take care of parameters with side-effecting
2751 function calls in them, this is required to take care
2752 of overlaying function parameters */
2753 geniCodeSEParms (parms,lvl);
2755 /* first the parameters */
2756 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2758 /* now call : if symbol then pcall */
2759 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2760 ic = newiCode (PCALL, left, NULL);
2762 ic = newiCode (CALL, left, NULL);
2764 IC_ARGS (ic) = left->operand.symOperand->args;
2765 type = copyLinkChain (operandType (left)->next);
2766 etype = getSpec (type);
2767 SPEC_EXTR (etype) = 0;
2768 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2772 /* stack adjustment after call */
2773 ic->parmBytes = stack;
2778 /*-----------------------------------------------------------------*/
2779 /* geniCodeReceive - generate intermediate code for "receive" */
2780 /*-----------------------------------------------------------------*/
2782 geniCodeReceive (value * args)
2784 /* for all arguments that are passed in registers */
2788 if (IS_REGPARM (args->etype))
2790 operand *opr = operandFromValue (args);
2792 symbol *sym = OP_SYMBOL (opr);
2795 /* we will use it after all optimizations
2796 and before liveRange calculation */
2797 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2800 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2801 options.stackAuto == 0 &&
2802 /* !TARGET_IS_DS390) */
2803 (!(options.model == MODEL_FLAT24)) )
2808 opl = newiTempOperand (args->type, 0);
2810 sym->reqv->key = sym->key;
2811 OP_SYMBOL (sym->reqv)->key = sym->key;
2812 OP_SYMBOL (sym->reqv)->isreqv = 1;
2813 OP_SYMBOL (sym->reqv)->islocal = 0;
2814 SPIL_LOC (sym->reqv) = sym;
2818 ic = newiCode (RECEIVE, NULL, NULL);
2819 currFunc->recvSize = getSize (sym->etype);
2820 IC_RESULT (ic) = opr;
2828 /*-----------------------------------------------------------------*/
2829 /* geniCodeFunctionBody - create the function body */
2830 /*-----------------------------------------------------------------*/
2832 geniCodeFunctionBody (ast * tree,int lvl)
2839 /* reset the auto generation */
2845 func = ast2iCode (tree->left,lvl+1);
2846 fetype = getSpec (operandType (func));
2848 savelineno = lineno;
2849 lineno = OP_SYMBOL (func)->lineDef;
2850 /* create an entry label */
2851 geniCodeLabel (entryLabel);
2852 lineno = savelineno;
2854 /* create a proc icode */
2855 ic = newiCode (FUNCTION, func, NULL);
2856 /* if the function has parmas then */
2857 /* save the parameters information */
2858 ic->argLabel.args = tree->values.args;
2859 ic->lineno = OP_SYMBOL (func)->lineDef;
2863 /* for all parameters that are passed
2864 on registers add a "receive" */
2865 geniCodeReceive (tree->values.args);
2867 /* generate code for the body */
2868 ast2iCode (tree->right,lvl+1);
2870 /* create a label for return */
2871 geniCodeLabel (returnLabel);
2873 /* now generate the end proc */
2874 ic = newiCode (ENDFUNCTION, func, NULL);
2879 /*-----------------------------------------------------------------*/
2880 /* geniCodeReturn - gen icode for 'return' statement */
2881 /*-----------------------------------------------------------------*/
2883 geniCodeReturn (operand * op)
2887 /* if the operand is present force an rvalue */
2889 op = geniCodeRValue (op, FALSE);
2891 ic = newiCode (RETURN, op, NULL);
2895 /*-----------------------------------------------------------------*/
2896 /* geniCodeIfx - generates code for extended if statement */
2897 /*-----------------------------------------------------------------*/
2899 geniCodeIfx (ast * tree,int lvl)
2902 operand *condition = ast2iCode (tree->left,lvl+1);
2905 /* if condition is null then exit */
2909 condition = geniCodeRValue (condition, FALSE);
2911 cetype = getSpec (operandType (condition));
2912 /* if the condition is a literal */
2913 if (IS_LITERAL (cetype))
2915 if (floatFromVal (condition->operand.valOperand))
2917 if (tree->trueLabel)
2918 geniCodeGoto (tree->trueLabel);
2924 if (tree->falseLabel)
2925 geniCodeGoto (tree->falseLabel);
2932 if (tree->trueLabel)
2934 ic = newiCodeCondition (condition,
2939 if (tree->falseLabel)
2940 geniCodeGoto (tree->falseLabel);
2944 ic = newiCodeCondition (condition,
2951 ast2iCode (tree->right,lvl+1);
2954 /*-----------------------------------------------------------------*/
2955 /* geniCodeJumpTable - tries to create a jump table for switch */
2956 /*-----------------------------------------------------------------*/
2958 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2960 int min = 0, max = 0, t, cnt = 0;
2967 if (!tree || !caseVals)
2970 /* the criteria for creating a jump table is */
2971 /* all integer numbers between the maximum & minimum must */
2972 /* be present , the maximum value should not exceed 255 */
2973 min = max = (int) floatFromVal (vch = caseVals);
2974 sprintf (buffer, "_case_%d_%d",
2975 tree->values.switchVals.swNum,
2977 addSet (&labels, newiTempLabel (buffer));
2979 /* if there is only one case value then no need */
2980 if (!(vch = vch->next))
2985 if (((t = (int) floatFromVal (vch)) - max) != 1)
2987 sprintf (buffer, "_case_%d_%d",
2988 tree->values.switchVals.swNum,
2990 addSet (&labels, newiTempLabel (buffer));
2996 /* if the number of case statements <= 2 then */
2997 /* it is not economical to create the jump table */
2998 /* since two compares are needed for boundary conditions */
2999 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3002 if (tree->values.switchVals.swDefault)
3003 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3005 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3007 falseLabel = newiTempLabel (buffer);
3009 /* so we can create a jumptable */
3010 /* first we rule out the boundary conditions */
3011 /* if only optimization says so */
3012 if (!optimize.noJTabBoundary)
3014 sym_link *cetype = getSpec (operandType (cond));
3015 /* no need to check the lower bound if
3016 the condition is unsigned & minimum value is zero */
3017 if (!(min == 0 && SPEC_USIGN (cetype)))
3019 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3020 ic = newiCodeCondition (boundary, falseLabel, NULL);
3024 /* now for upper bounds */
3025 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3026 ic = newiCodeCondition (boundary, falseLabel, NULL);
3030 /* if the min is not zero then we no make it zero */
3033 cond = geniCodeSubtract (cond, operandFromLit (min));
3034 setOperandType (cond, UCHARTYPE);
3037 /* now create the jumptable */
3038 ic = newiCode (JUMPTABLE, NULL, NULL);
3039 IC_JTCOND (ic) = cond;
3040 IC_JTLABELS (ic) = labels;
3045 /*-----------------------------------------------------------------*/
3046 /* geniCodeSwitch - changes a switch to a if statement */
3047 /*-----------------------------------------------------------------*/
3049 geniCodeSwitch (ast * tree,int lvl)
3052 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3053 value *caseVals = tree->values.switchVals.swVals;
3054 symbol *trueLabel, *falseLabel;
3056 /* if we can make this a jump table */
3057 if (geniCodeJumpTable (cond, caseVals, tree))
3058 goto jumpTable; /* no need for the comparison */
3060 /* for the cases defined do */
3064 operand *compare = geniCodeLogic (cond,
3065 operandFromValue (caseVals),
3068 sprintf (buffer, "_case_%d_%d",
3069 tree->values.switchVals.swNum,
3070 (int) floatFromVal (caseVals));
3071 trueLabel = newiTempLabel (buffer);
3073 ic = newiCodeCondition (compare, trueLabel, NULL);
3075 caseVals = caseVals->next;
3080 /* if default is present then goto break else break */
3081 if (tree->values.switchVals.swDefault)
3082 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3084 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3086 falseLabel = newiTempLabel (buffer);
3087 geniCodeGoto (falseLabel);
3090 ast2iCode (tree->right,lvl+1);
3093 /*-----------------------------------------------------------------*/
3094 /* geniCodeInline - intermediate code for inline assembler */
3095 /*-----------------------------------------------------------------*/
3097 geniCodeInline (ast * tree)
3101 ic = newiCode (INLINEASM, NULL, NULL);
3102 IC_INLINE (ic) = tree->values.inlineasm;
3106 /*-----------------------------------------------------------------*/
3107 /* geniCodeArrayInit - intermediate code for array initializer */
3108 /*-----------------------------------------------------------------*/
3110 geniCodeArrayInit (ast * tree, operand *array)
3114 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3115 ic = newiCode (ARRAYINIT, array, NULL);
3116 IC_ARRAYILIST (ic) = tree->values.constlist;
3118 operand *left=newOperand(), *right=newOperand();
3119 left->type=right->type=SYMBOL;
3120 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3121 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3122 ic = newiCode (ARRAYINIT, left, right);
3127 /*-----------------------------------------------------------------*/
3128 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3129 /* particular case. Ie : assigning or dereferencing array or ptr */
3130 /*-----------------------------------------------------------------*/
3131 set * lvaluereqSet = NULL;
3132 typedef struct lvalItem
3139 /*-----------------------------------------------------------------*/
3140 /* addLvaluereq - add a flag for lvalreq for current ast level */
3141 /*-----------------------------------------------------------------*/
3142 void addLvaluereq(int lvl)
3144 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3147 addSetHead(&lvaluereqSet,lpItem);
3150 /*-----------------------------------------------------------------*/
3151 /* delLvaluereq - del a flag for lvalreq for current ast level */
3152 /*-----------------------------------------------------------------*/
3156 lpItem = getSet(&lvaluereqSet);
3157 if(lpItem) free(lpItem);
3159 /*-----------------------------------------------------------------*/
3160 /* clearLvaluereq - clear lvalreq flag */
3161 /*-----------------------------------------------------------------*/
3162 void clearLvaluereq()
3165 lpItem = peekSet(lvaluereqSet);
3166 if(lpItem) lpItem->req = 0;
3168 /*-----------------------------------------------------------------*/
3169 /* getLvaluereq - get the last lvalreq level */
3170 /*-----------------------------------------------------------------*/
3171 int getLvaluereqLvl()
3174 lpItem = peekSet(lvaluereqSet);
3175 if(lpItem) return lpItem->lvl;
3178 /*-----------------------------------------------------------------*/
3179 /* isLvaluereq - is lvalreq valid for this level ? */
3180 /*-----------------------------------------------------------------*/
3181 int isLvaluereq(int lvl)
3184 lpItem = peekSet(lvaluereqSet);
3185 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3189 /*-----------------------------------------------------------------*/
3190 /* ast2iCode - creates an icodeList from an ast */
3191 /*-----------------------------------------------------------------*/
3193 ast2iCode (ast * tree,int lvl)
3195 operand *left = NULL;
3196 operand *right = NULL;
3199 /* set the global variables for filename & line number */
3201 filename = tree->filename;
3203 lineno = tree->lineno;
3205 block = tree->block;
3207 scopeLevel = tree->level;
3209 if (tree->type == EX_VALUE)
3210 return operandFromValue (tree->opval.val);
3212 if (tree->type == EX_LINK)
3213 return operandFromLink (tree->opval.lnk);
3215 /* if we find a nullop */
3216 if (tree->type == EX_OP &&
3217 (tree->opval.op == NULLOP ||
3218 tree->opval.op == BLOCK))
3220 ast2iCode (tree->left,lvl+1);
3221 ast2iCode (tree->right,lvl+1);
3225 /* special cases for not evaluating */
3226 if (tree->opval.op != ':' &&
3227 tree->opval.op != '?' &&
3228 tree->opval.op != CALL &&
3229 tree->opval.op != IFX &&
3230 tree->opval.op != LABEL &&
3231 tree->opval.op != GOTO &&
3232 tree->opval.op != SWITCH &&
3233 tree->opval.op != FUNCTION &&
3234 tree->opval.op != INLINEASM)
3237 if (IS_ASSIGN_OP (tree->opval.op) ||
3238 IS_DEREF_OP (tree) ||
3239 (tree->opval.op == '&' && !tree->right) ||
3240 tree->opval.op == PTR_OP)
3243 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3244 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3247 left = operandFromAst (tree->left,lvl);
3249 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3250 left = geniCodeRValue (left, TRUE);
3254 left = operandFromAst (tree->left,lvl);
3256 if (tree->opval.op == INC_OP ||
3257 tree->opval.op == DEC_OP)
3260 right = operandFromAst (tree->right,lvl);
3265 right = operandFromAst (tree->right,lvl);
3269 /* now depending on the type of operand */
3270 /* this will be a biggy */
3271 switch (tree->opval.op)
3274 case '[': /* array operation */
3276 sym_link *ltype = operandType (left);
3277 left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3278 right = geniCodeRValue (right, TRUE);
3281 return geniCodeArray (left, right,lvl);
3283 case '.': /* structure dereference */
3284 if (IS_PTR (operandType (left)))
3285 left = geniCodeRValue (left, TRUE);
3287 left = geniCodeRValue (left, FALSE);
3289 return geniCodeStruct (left, right, tree->lvalue);
3291 case PTR_OP: /* structure pointer dereference */
3294 pType = operandType (left);
3295 left = geniCodeRValue (left, TRUE);
3297 setOClass (pType, getSpec (operandType (left)));
3300 return geniCodeStruct (left, right, tree->lvalue);
3302 case INC_OP: /* increment operator */
3304 return geniCodePostInc (left);
3306 return geniCodePreInc (right);
3308 case DEC_OP: /* decrement operator */
3310 return geniCodePostDec (left);
3312 return geniCodePreDec (right);
3314 case '&': /* bitwise and or address of operator */
3316 { /* this is a bitwise operator */
3317 left = geniCodeRValue (left, FALSE);
3318 right = geniCodeRValue (right, FALSE);
3319 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3322 return geniCodeAddressOf (left);
3324 case '|': /* bitwise or & xor */
3326 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3327 geniCodeRValue (right, FALSE),
3332 return geniCodeDivision (geniCodeRValue (left, FALSE),
3333 geniCodeRValue (right, FALSE));
3336 return geniCodeModulus (geniCodeRValue (left, FALSE),
3337 geniCodeRValue (right, FALSE));
3340 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3341 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3343 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3347 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3348 geniCodeRValue (right, FALSE));
3350 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3354 return geniCodeAdd (geniCodeRValue (left, FALSE),
3355 geniCodeRValue (right, FALSE),lvl);
3357 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3360 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3361 geniCodeRValue (right, FALSE));
3364 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3365 geniCodeRValue (right, FALSE));
3367 return geniCodeCast (operandType (left),
3368 geniCodeRValue (right, FALSE), FALSE);
3374 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3378 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3379 setOperandType (op, UCHARTYPE);
3390 return geniCodeLogic (geniCodeRValue (left, FALSE),
3391 geniCodeRValue (right, FALSE),
3394 return geniCodeConditional (tree,lvl);
3397 return operandFromLit (getSize (tree->right->ftype));
3401 sym_link *rtype = operandType (right);
3402 sym_link *ltype = operandType (left);
3403 if (IS_PTR (rtype) && IS_ITEMP (right)
3404 && right->isaddr && compareType (rtype->next, ltype) == 1)
3405 right = geniCodeRValue (right, TRUE);
3407 right = geniCodeRValue (right, FALSE);
3409 geniCodeAssign (left, right, 0);
3414 geniCodeAssign (left,
3415 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3417 geniCodeRValue (right, FALSE),FALSE), 0);
3421 geniCodeAssign (left,
3422 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3424 geniCodeRValue (right, FALSE)), 0);
3427 geniCodeAssign (left,
3428 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3430 geniCodeRValue (right, FALSE)), 0);
3433 sym_link *rtype = operandType (right);
3434 sym_link *ltype = operandType (left);
3435 if (IS_PTR (rtype) && IS_ITEMP (right)
3436 && right->isaddr && compareType (rtype->next, ltype) == 1)
3437 right = geniCodeRValue (right, TRUE);
3439 right = geniCodeRValue (right, FALSE);
3442 return geniCodeAssign (left,
3443 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3449 sym_link *rtype = operandType (right);
3450 sym_link *ltype = operandType (left);
3451 if (IS_PTR (rtype) && IS_ITEMP (right)
3452 && right->isaddr && compareType (rtype->next, ltype) == 1)
3454 right = geniCodeRValue (right, TRUE);
3458 right = geniCodeRValue (right, FALSE);
3461 geniCodeAssign (left,
3462 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3468 geniCodeAssign (left,
3469 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3471 geniCodeRValue (right, FALSE)), 0);
3474 geniCodeAssign (left,
3475 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3477 geniCodeRValue (right, FALSE)), 0);
3480 geniCodeAssign (left,
3481 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3483 geniCodeRValue (right, FALSE),
3485 operandType (left)), 0);
3488 geniCodeAssign (left,
3489 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3491 geniCodeRValue (right, FALSE),
3493 operandType (left)), 0);
3496 geniCodeAssign (left,
3497 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3499 geniCodeRValue (right, FALSE),
3501 operandType (left)), 0);
3503 return geniCodeRValue (right, FALSE);
3506 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3509 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3510 return ast2iCode (tree->right,lvl+1);
3513 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3514 return ast2iCode (tree->right,lvl+1);
3517 geniCodeFunctionBody (tree,lvl);
3521 geniCodeReturn (right);
3525 geniCodeIfx (tree,lvl);
3529 geniCodeSwitch (tree,lvl);
3533 geniCodeInline (tree);
3537 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3544 /*-----------------------------------------------------------------*/
3545 /* reverseICChain - gets from the list and creates a linkedlist */
3546 /*-----------------------------------------------------------------*/
3553 while ((loop = getSet (&iCodeChain)))
3565 /*-----------------------------------------------------------------*/
3566 /* iCodeFromAst - given an ast will convert it to iCode */
3567 /*-----------------------------------------------------------------*/
3569 iCodeFromAst (ast * tree)
3571 returnLabel = newiTempLabel ("_return");
3572 entryLabel = newiTempLabel ("_entry");
3574 return reverseiCChain ();