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 -------------------------------------------------------------------------*/
29 /*-----------------------------------------------------------------*/
30 /* global variables */
32 set *iCodeChain = NULL;
42 symbol *returnLabel; /* function return label */
43 symbol *entryLabel; /* function entry label */
45 /*-----------------------------------------------------------------*/
46 /* forward definition of some functions */
47 operand *geniCodeDivision (operand *, operand *);
48 operand *geniCodeAssign (operand *, operand *, int);
49 operand *geniCodeArray (operand *, operand *,int);
50 operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
55 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
56 /* forward definition of ic print functions */
57 PRINTFUNC (picGetValueAtAddr);
58 PRINTFUNC (picSetValueAtAddr);
59 PRINTFUNC (picAddrOf);
60 PRINTFUNC (picGeneric);
61 PRINTFUNC (picGenericOne);
63 PRINTFUNC (picAssign);
67 PRINTFUNC (picJumpTable);
68 PRINTFUNC (picInline);
69 PRINTFUNC (picReceive);
71 iCodeTable codeTable[] =
73 {'!', "not", picGenericOne, NULL},
74 {'~', "~", picGenericOne, NULL},
75 {RRC, "rrc", picGenericOne, NULL},
76 {RLC, "rlc", picGenericOne, NULL},
77 {GETHBIT, "ghbit", picGenericOne, NULL},
78 {UNARYMINUS, "-", picGenericOne, NULL},
79 {IPUSH, "push", picGenericOne, NULL},
80 {IPOP, "pop", picGenericOne, NULL},
81 {CALL, "call", picGenericOne, NULL},
82 {PCALL, "pcall", picGenericOne, NULL},
83 {FUNCTION, "proc", picGenericOne, NULL},
84 {ENDFUNCTION, "eproc", picGenericOne, NULL},
85 {RETURN, "ret", picGenericOne, NULL},
86 {'+', "+", picGeneric, NULL},
87 {'-', "-", picGeneric, NULL},
88 {'*', "*", picGeneric, NULL},
89 {'/', "/", picGeneric, NULL},
90 {'%', "%", picGeneric, NULL},
91 {'>', ">", picGeneric, NULL},
92 {'<', "<", picGeneric, NULL},
93 {LE_OP, "<=", picGeneric, NULL},
94 {GE_OP, ">=", picGeneric, NULL},
95 {EQ_OP, "==", picGeneric, NULL},
96 {NE_OP, "!=", picGeneric, NULL},
97 {AND_OP, "&&", picGeneric, NULL},
98 {OR_OP, "||", picGeneric, NULL},
99 {'^', "^", picGeneric, NULL},
100 {'|', "|", picGeneric, NULL},
101 {BITWISEAND, "&", picGeneric, NULL},
102 {LEFT_OP, "<<", picGeneric, NULL},
103 {RIGHT_OP, ">>", picGeneric, NULL},
104 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
105 {ADDRESS_OF, "&", picAddrOf, NULL},
106 {CAST, "<>", picCast, NULL},
107 {'=', ":=", picAssign, NULL},
108 {LABEL, "", picLabel, NULL},
109 {GOTO, "", picGoto, NULL},
110 {JUMPTABLE, "jtab", picJumpTable, NULL},
111 {IFX, "if", picIfx, NULL},
112 {INLINEASM, "", picInline, NULL},
113 {RECEIVE, "recv", picReceive, NULL},
114 {SEND, "send", picGenericOne, NULL},
115 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
118 /*-----------------------------------------------------------------*/
119 /* checkConstantRange: check a constant against the type */
120 /*-----------------------------------------------------------------*/
122 /* pedantic=0: allmost anything is allowed as long as the absolute
123 value is within the bit range of the type, and -1 is treated as
124 0xf..f for unsigned types (e.g. in assign)
125 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
126 pedantic>1: "char c=200" is not allowed (evaluates to -56)
129 void checkConstantRange(sym_link *ltype, value *val, char *msg,
136 max = pow ((double)2.0, (double)bitsForType(ltype));
138 if (SPEC_LONG(val->type)) {
139 if (SPEC_USIGN(val->type)) {
140 v=SPEC_CVAL(val->type).v_ulong;
142 v=SPEC_CVAL(val->type).v_long;
145 if (SPEC_USIGN(val->type)) {
146 v=SPEC_CVAL(val->type).v_uint;
148 v=SPEC_CVAL(val->type).v_int;
154 // this could be a good idea
155 if (options.pedantic)
159 if (SPEC_NOUN(ltype)==FLOAT) {
164 if (!SPEC_USIGN(val->type) && v<0) {
166 if (SPEC_USIGN(ltype) && (pedantic>1)) {
172 // if very pedantic: "char c=200" is not allowed
173 if (pedantic>1 && !SPEC_USIGN(ltype)) {
174 max = max/2 + negative;
181 #if 0 // temporary disabled, leaving the warning as a reminder
183 SNPRINTF (message, sizeof(message), "for %s %s in %s",
184 SPEC_USIGN(ltype) ? "unsigned" : "signed",
185 nounName(ltype), msg);
186 werror (W_CONST_RANGE, message);
194 /*-----------------------------------------------------------------*/
195 /* operandName - returns the name of the operand */
196 /*-----------------------------------------------------------------*/
198 printOperand (operand * op, FILE * file)
215 opetype = getSpec (operandType (op));
216 if (SPEC_NOUN (opetype) == V_FLOAT)
217 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
219 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
220 printTypeChain (operandType (op), file);
227 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
228 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
230 OP_LIVEFROM (op), OP_LIVETO (op),
231 OP_SYMBOL (op)->stack,
232 op->isaddr, OP_SYMBOL (op)->isreqv,
233 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
234 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
238 printTypeChain (operandType (op), file);
239 if (SPIL_LOC (op) && IS_ITEMP (op))
240 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
245 /* if assigned to registers */
246 if (OP_SYMBOL (op)->nRegs)
248 if (OP_SYMBOL (op)->isspilt)
250 if (!OP_SYMBOL (op)->remat)
251 if (OP_SYMBOL (op)->usl.spillLoc)
252 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
253 OP_SYMBOL (op)->usl.spillLoc->rname :
254 OP_SYMBOL (op)->usl.spillLoc->name));
256 fprintf (file, "[err]");
258 fprintf (file, "[remat]");
264 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
265 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
270 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
271 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
272 /* if assigned to registers */
273 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
277 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
278 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
279 OP_SYMBOL (op)->regs[i]->name :
288 printTypeChain (op->operand.typeOperand, file);
294 fprintf (file, "\n");
299 /*-----------------------------------------------------------------*/
300 /* print functions */
301 /*-----------------------------------------------------------------*/
302 PRINTFUNC (picGetValueAtAddr)
305 printOperand (IC_RESULT (ic), of);
308 printOperand (IC_LEFT (ic), of);
314 PRINTFUNC (picSetValueAtAddr)
318 printOperand (IC_LEFT (ic), of);
319 fprintf (of, "] = ");
320 printOperand (IC_RIGHT (ic), of);
324 PRINTFUNC (picAddrOf)
327 printOperand (IC_RESULT (ic), of);
328 if (IS_ITEMP (IC_LEFT (ic)))
331 fprintf (of, " = &[");
332 printOperand (IC_LEFT (ic), of);
335 if (IS_ITEMP (IC_LEFT (ic)))
336 fprintf (of, " offsetAdd ");
339 printOperand (IC_RIGHT (ic), of);
341 if (IS_ITEMP (IC_LEFT (ic)))
347 PRINTFUNC (picJumpTable)
352 fprintf (of, "%s\t", s);
353 printOperand (IC_JTCOND (ic), of);
355 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
356 sym = setNextItem (IC_JTLABELS (ic)))
357 fprintf (of, "\t\t\t%s\n", sym->name);
360 PRINTFUNC (picGeneric)
363 printOperand (IC_RESULT (ic), of);
365 printOperand (IC_LEFT (ic), of);
366 fprintf (of, " %s ", s);
367 printOperand (IC_RIGHT (ic), of);
371 PRINTFUNC (picGenericOne)
376 printOperand (IC_RESULT (ic), of);
382 fprintf (of, "%s ", s);
383 printOperand (IC_LEFT (ic), of);
386 if (!IC_RESULT (ic) && !IC_LEFT (ic))
389 if (ic->op == SEND || ic->op == RECEIVE) {
390 fprintf(of,"{argreg = %d}",ic->argreg);
398 printOperand (IC_RESULT (ic), of);
400 printOperand (IC_LEFT (ic), of);
401 printOperand (IC_RIGHT (ic), of);
406 PRINTFUNC (picAssign)
410 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
413 printOperand (IC_RESULT (ic), of);
415 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
418 fprintf (of, " %s ", s);
419 printOperand (IC_RIGHT (ic), of);
426 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
432 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
439 printOperand (IC_COND (ic), of);
442 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
445 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
447 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
451 PRINTFUNC (picInline)
453 fprintf (of, "%s", IC_INLINE (ic));
456 PRINTFUNC (picReceive)
458 printOperand (IC_RESULT (ic), of);
459 fprintf (of, " = %s ", s);
460 printOperand (IC_LEFT (ic), of);
464 /*-----------------------------------------------------------------*/
465 /* piCode - prints one iCode */
466 /*-----------------------------------------------------------------*/
468 piCode (void *item, FILE * of)
476 icTab = getTableEntry (ic->op);
477 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
478 ic->filename, ic->lineno,
479 ic->seq, ic->key, ic->depth, ic->supportRtn);
480 icTab->iCodePrint (of, ic, icTab->printName);
486 printiCChain(ic,stdout);
488 /*-----------------------------------------------------------------*/
489 /* printiCChain - prints intermediate code for humans */
490 /*-----------------------------------------------------------------*/
492 printiCChain (iCode * icChain, FILE * of)
499 for (loop = icChain; loop; loop = loop->next)
501 if ((icTab = getTableEntry (loop->op)))
503 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
504 loop->filename, loop->lineno,
505 loop->seq, loop->key, loop->depth, loop->supportRtn);
507 icTab->iCodePrint (of, loop, icTab->printName);
513 /*-----------------------------------------------------------------*/
514 /* newOperand - allocate, init & return a new iCode */
515 /*-----------------------------------------------------------------*/
521 op = Safe_alloc ( sizeof (operand));
527 /*-----------------------------------------------------------------*/
528 /* newiCode - create and return a new iCode entry initialised */
529 /*-----------------------------------------------------------------*/
531 newiCode (int op, operand * left, operand * right)
535 ic = Safe_alloc ( sizeof (iCode));
538 ic->filename = filename;
540 ic->level = scopeLevel;
542 ic->key = iCodeKey++;
544 IC_RIGHT (ic) = right;
549 /*-----------------------------------------------------------------*/
550 /* newiCode for conditional statements */
551 /*-----------------------------------------------------------------*/
553 newiCodeCondition (operand * condition,
559 if (IS_VOID(operandType(condition))) {
560 werror(E_VOID_VALUE_USED);
563 ic = newiCode (IFX, NULL, NULL);
564 IC_COND (ic) = condition;
565 IC_TRUE (ic) = trueLabel;
566 IC_FALSE (ic) = falseLabel;
570 /*-----------------------------------------------------------------*/
571 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
572 /*-----------------------------------------------------------------*/
574 newiCodeLabelGoto (int op, symbol * label)
578 ic = newiCode (op, NULL, NULL);
582 IC_RIGHT (ic) = NULL;
583 IC_RESULT (ic) = NULL;
587 /*-----------------------------------------------------------------*/
588 /* newiTemp - allocate & return a newItemp Variable */
589 /*-----------------------------------------------------------------*/
597 SNPRINTF (buffer, sizeof(buffer), "%s", s);
601 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
604 itmp = newSymbol (buffer, 1);
605 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
611 /*-----------------------------------------------------------------*/
612 /* newiTempLabel - creates a temp variable label */
613 /*-----------------------------------------------------------------*/
615 newiTempLabel (char *s)
619 /* check if this alredy exists */
620 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
625 itmplbl = newSymbol (s, 1);
629 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
630 itmplbl = newSymbol (buffer, 1);
635 itmplbl->key = labelKey++;
636 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
640 /*-----------------------------------------------------------------*/
641 /* newiTempPreheaderLabel - creates a new preheader label */
642 /*-----------------------------------------------------------------*/
644 newiTempPreheaderLabel ()
648 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
649 itmplbl = newSymbol (buffer, 1);
653 itmplbl->key = labelKey++;
654 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
659 /*-----------------------------------------------------------------*/
660 /* initiCode - initialises some iCode related stuff */
661 /*-----------------------------------------------------------------*/
668 /*-----------------------------------------------------------------*/
669 /* copyiCode - make a copy of the iCode given */
670 /*-----------------------------------------------------------------*/
672 copyiCode (iCode * ic)
674 iCode *nic = newiCode (ic->op, NULL, NULL);
676 nic->lineno = ic->lineno;
677 nic->filename = ic->filename;
678 nic->block = ic->block;
679 nic->level = ic->level;
680 nic->parmBytes = ic->parmBytes;
682 /* deal with the special cases first */
686 IC_COND (nic) = operandFromOperand (IC_COND (ic));
687 IC_TRUE (nic) = IC_TRUE (ic);
688 IC_FALSE (nic) = IC_FALSE (ic);
692 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
693 IC_JTLABELS (nic) = IC_JTLABELS (ic);
698 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
699 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
703 IC_INLINE (nic) = IC_INLINE (ic);
707 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
711 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
712 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
713 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
719 /*-----------------------------------------------------------------*/
720 /* getTableEntry - gets the table entry for the given operator */
721 /*-----------------------------------------------------------------*/
723 getTableEntry (int oper)
727 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
728 if (oper == codeTable[i].icode)
729 return &codeTable[i];
734 /*-----------------------------------------------------------------*/
735 /* newiTempOperand - new intermediate temp operand */
736 /*-----------------------------------------------------------------*/
738 newiTempOperand (sym_link * type, char throwType)
741 operand *op = newOperand ();
745 itmp = newiTemp (NULL);
747 etype = getSpec (type);
749 if (IS_LITERAL (etype))
752 /* copy the type information */
754 itmp->etype = getSpec (itmp->type = (throwType ? type :
755 copyLinkChain (type)));
756 if (IS_LITERAL (itmp->etype))
758 SPEC_SCLS (itmp->etype) = S_REGISTER;
759 SPEC_OCLS (itmp->etype) = reg;
762 op->operand.symOperand = itmp;
763 op->key = itmp->key = ++operandKey;
767 /*-----------------------------------------------------------------*/
768 /* operandType - returns the type chain for an operand */
769 /*-----------------------------------------------------------------*/
771 operandType (operand * op)
773 /* depending on type of operand */
778 return op->operand.valOperand->type;
781 return op->operand.symOperand->type;
784 return op->operand.typeOperand;
786 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
787 " operand type not known ");
788 assert (0); /* should never come here */
789 /* Just to keep the compiler happy */
790 return (sym_link *) 0;
794 /*-----------------------------------------------------------------*/
795 /* isParamterToCall - will return 1 if op is a parameter to args */
796 /*-----------------------------------------------------------------*/
798 isParameterToCall (value * args, operand * op)
802 wassert (IS_SYMOP(op));
807 isSymbolEqual (op->operand.symOperand, tval->sym))
814 /*-----------------------------------------------------------------*/
815 /* isOperandGlobal - return 1 if operand is a global variable */
816 /*-----------------------------------------------------------------*/
818 isOperandGlobal (operand * op)
827 (op->operand.symOperand->level == 0 ||
828 IS_STATIC (op->operand.symOperand->etype) ||
829 IS_EXTERN (op->operand.symOperand->etype))
836 /*-----------------------------------------------------------------*/
837 /* isOperandVolatile - return 1 if the operand is volatile */
838 /*-----------------------------------------------------------------*/
840 isOperandVolatile (operand * op, bool chkTemp)
845 if (IS_ITEMP (op) && !chkTemp)
848 return IS_VOLATILE(operandType(op));
851 /*-----------------------------------------------------------------*/
852 /* isOperandLiteral - returns 1 if an operand contains a literal */
853 /*-----------------------------------------------------------------*/
855 isOperandLiteral (operand * op)
862 opetype = getSpec (operandType (op));
864 if (IS_LITERAL (opetype))
870 /*-----------------------------------------------------------------*/
871 /* isOperandInFarSpace - will return true if operand is in farSpace */
872 /*-----------------------------------------------------------------*/
874 isOperandInFarSpace (operand * op)
884 if (!IS_TRUE_SYMOP (op))
887 etype = SPIL_LOC (op)->etype;
893 etype = getSpec (operandType (op));
895 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
898 /*------------------------------------------------------------------*/
899 /* isOperandInDirSpace - will return true if operand is in dirSpace */
900 /*------------------------------------------------------------------*/
902 isOperandInDirSpace (operand * op)
912 if (!IS_TRUE_SYMOP (op))
915 etype = SPIL_LOC (op)->etype;
921 etype = getSpec (operandType (op));
923 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
926 /*--------------------------------------------------------------------*/
927 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
928 /*--------------------------------------------------------------------*/
930 isOperandInCodeSpace (operand * op)
940 etype = getSpec (operandType (op));
942 if (!IS_TRUE_SYMOP (op))
945 etype = SPIL_LOC (op)->etype;
951 etype = getSpec (operandType (op));
953 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
956 /*-----------------------------------------------------------------*/
957 /* isOperandOnStack - will return true if operand is on stack */
958 /*-----------------------------------------------------------------*/
960 isOperandOnStack (operand * op)
970 etype = getSpec (operandType (op));
971 if (IN_STACK (etype) ||
972 OP_SYMBOL(op)->onStack ||
973 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
979 /*-----------------------------------------------------------------*/
980 /* operandLitValue - literal value of an operand */
981 /*-----------------------------------------------------------------*/
983 operandLitValue (operand * op)
985 assert (isOperandLiteral (op));
987 return floatFromVal (op->operand.valOperand);
990 /*-----------------------------------------------------------------*/
991 /* getBuiltInParms - returns parameters to a builtin functions */
992 /*-----------------------------------------------------------------*/
993 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
998 /* builtin functions uses only SEND for parameters */
999 while (ic->op != CALL) {
1000 assert(ic->op == SEND && ic->builtinSEND);
1001 ic->generated = 1; /* mark the icode as generated */
1002 parms[*pcount] = IC_LEFT(ic);
1008 /* make sure this is a builtin function call */
1009 assert(IS_SYMOP(IC_LEFT(ic)));
1010 ftype = operandType(IC_LEFT(ic));
1011 assert(IFFUNC_ISBUILTIN(ftype));
1015 /*-----------------------------------------------------------------*/
1016 /* operandOperation - perforoms operations on operands */
1017 /*-----------------------------------------------------------------*/
1019 operandOperation (operand * left, operand * right,
1020 int op, sym_link * type)
1022 sym_link *let , *ret=NULL;
1023 operand *retval = (operand *) 0;
1025 assert (isOperandLiteral (left));
1026 let = getSpec(operandType(left));
1028 assert (isOperandLiteral (right));
1029 ret = getSpec(operandType(left));
1035 retval = operandFromValue (valCastLiteral (type,
1036 operandLitValue (left) +
1037 operandLitValue (right)));
1040 retval = operandFromValue (valCastLiteral (type,
1041 operandLitValue (left) -
1042 operandLitValue (right)));
1045 retval = operandFromValue (valCastLiteral (type,
1046 operandLitValue (left) *
1047 operandLitValue (right)));
1050 if ((unsigned long) operandLitValue (right) == 0)
1052 werror (E_DIVIDE_BY_ZERO);
1057 retval = operandFromValue (valCastLiteral (type,
1058 operandLitValue (left) /
1059 operandLitValue (right)));
1062 if ((unsigned long) operandLitValue (right) == 0) {
1063 werror (E_DIVIDE_BY_ZERO);
1067 retval = operandFromLit ((SPEC_USIGN(let) ?
1068 (unsigned long) operandLitValue (left) :
1069 (long) operandLitValue (left)) %
1071 (unsigned long) operandLitValue (right) :
1072 (long) operandLitValue (right)));
1076 retval = operandFromLit ((SPEC_USIGN(let) ?
1077 (unsigned long) operandLitValue (left) :
1078 (long) operandLitValue (left)) <<
1080 (unsigned long) operandLitValue (right) :
1081 (long) operandLitValue (right)));
1084 double lval = operandLitValue(left), rval = operandLitValue(right);
1086 switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
1088 case 0: // left=unsigned right=unsigned
1089 res=(unsigned long)lval >> (unsigned long)rval;
1091 case 1: // left=unsigned right=signed
1092 res=(unsigned long)lval >> (signed long)rval;
1094 case 2: // left=signed right=unsigned
1095 res=(signed long)lval >> (unsigned long)rval;
1097 case 3: // left=signed right=signed
1098 res=(signed long)lval >> (signed long)rval;
1101 retval = operandFromLit (res);
1105 retval = operandFromLit (operandLitValue (left) ==
1106 operandLitValue (right));
1109 retval = operandFromLit (operandLitValue (left) <
1110 operandLitValue (right));
1113 retval = operandFromLit (operandLitValue (left) <=
1114 operandLitValue (right));
1117 retval = operandFromLit (operandLitValue (left) !=
1118 operandLitValue (right));
1121 retval = operandFromLit (operandLitValue (left) >
1122 operandLitValue (right));
1125 retval = operandFromLit (operandLitValue (left) >=
1126 operandLitValue (right));
1129 retval = operandFromLit ((long)operandLitValue(left) &
1130 (long)operandLitValue(right));
1133 retval = operandFromLit ((long)operandLitValue (left) |
1134 (long)operandLitValue (right));
1137 retval = operandFromLit ((long)operandLitValue (left) ^
1138 (long)operandLitValue (right));
1141 retval = operandFromLit (operandLitValue (left) &&
1142 operandLitValue (right));
1145 retval = operandFromLit (operandLitValue (left) ||
1146 operandLitValue (right));
1150 long i = (long) operandLitValue (left);
1152 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1158 long i = (long) operandLitValue (left);
1160 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1166 retval = operandFromLit (-1 * operandLitValue (left));
1170 retval = operandFromLit (~((long) operandLitValue (left)));
1174 retval = operandFromLit (!operandLitValue (left));
1178 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1179 " operandOperation invalid operator ");
1187 /*-----------------------------------------------------------------*/
1188 /* isOperandEqual - compares two operand & return 1 if they r = */
1189 /*-----------------------------------------------------------------*/
1191 isOperandEqual (operand * left, operand * right)
1193 /* if the pointers are equal then they are equal */
1197 /* if either of them null then false */
1198 if (!left || !right)
1201 if (left->type != right->type)
1204 if (IS_SYMOP (left) && IS_SYMOP (right))
1205 return left->key == right->key;
1207 /* if types are the same */
1211 return isSymbolEqual (left->operand.symOperand,
1212 right->operand.symOperand);
1214 return (floatFromVal (left->operand.valOperand) ==
1215 floatFromVal (right->operand.valOperand));
1217 if (compareType (left->operand.typeOperand,
1218 right->operand.typeOperand) == 1)
1225 /*-------------------------------------------------------------------*/
1226 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1227 /*-------------------------------------------------------------------*/
1229 isiCodeEqual (iCode * left, iCode * right)
1231 /* if the same pointer */
1235 /* if either of them null */
1236 if (!left || !right)
1239 /* if operand are the same */
1240 if (left->op == right->op)
1243 /* compare all the elements depending on type */
1244 if (left->op != IFX)
1246 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1248 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1254 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1256 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1258 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1267 /*-----------------------------------------------------------------*/
1268 /* newiTempFromOp - create a temp Operand with same attributes */
1269 /*-----------------------------------------------------------------*/
1271 newiTempFromOp (operand * op)
1281 nop = newiTempOperand (operandType (op), TRUE);
1282 nop->isaddr = op->isaddr;
1283 nop->isvolatile = op->isvolatile;
1284 nop->isGlobal = op->isGlobal;
1285 nop->isLiteral = op->isLiteral;
1286 nop->usesDefs = op->usesDefs;
1287 nop->isParm = op->isParm;
1291 /*-----------------------------------------------------------------*/
1292 /* operand from operand - creates an operand holder for the type */
1293 /*-----------------------------------------------------------------*/
1295 operandFromOperand (operand * op)
1301 nop = newOperand ();
1302 nop->type = op->type;
1303 nop->isaddr = op->isaddr;
1305 nop->isvolatile = op->isvolatile;
1306 nop->isGlobal = op->isGlobal;
1307 nop->isLiteral = op->isLiteral;
1308 nop->usesDefs = op->usesDefs;
1309 nop->isParm = op->isParm;
1314 nop->operand.symOperand = op->operand.symOperand;
1317 nop->operand.valOperand = op->operand.valOperand;
1320 nop->operand.typeOperand = op->operand.typeOperand;
1327 /*-----------------------------------------------------------------*/
1328 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1329 /*-----------------------------------------------------------------*/
1331 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1333 operand *nop = operandFromOperand (op);
1335 if (nop->type == SYMBOL)
1337 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1338 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1344 /*-----------------------------------------------------------------*/
1345 /* operandFromSymbol - creates an operand from a symbol */
1346 /*-----------------------------------------------------------------*/
1348 operandFromSymbol (symbol * sym)
1353 /* if the symbol's type is a literal */
1354 /* then it is an enumerator type */
1355 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1356 return operandFromValue (valFromType (sym->etype));
1359 sym->key = ++operandKey;
1361 /* if this an implicit variable, means struct/union */
1362 /* member so just return it */
1363 if (sym->implicit || IS_FUNC (sym->type))
1367 op->operand.symOperand = sym;
1369 op->isvolatile = isOperandVolatile (op, TRUE);
1370 op->isGlobal = isOperandGlobal (op);
1374 /* under the following conditions create a
1375 register equivalent for a local symbol */
1376 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1377 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1378 (!(options.model == MODEL_FLAT24)) ) &&
1379 options.stackAuto == 0)
1382 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1383 !IS_FUNC (sym->type) && /* not a function */
1384 !sym->_isparm && /* not a parameter */
1385 sym->level && /* is a local variable */
1386 !sym->addrtaken && /* whose address has not been taken */
1387 !sym->reqv && /* does not already have a reg equivalence */
1388 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1389 !IS_STATIC (sym->etype) && /* and not declared static */
1390 !sym->islbl && /* not a label */
1391 ok && /* farspace check */
1392 !IS_BITVAR (sym->etype) /* not a bit variable */
1396 /* we will use it after all optimizations
1397 and before liveRange calculation */
1398 sym->reqv = newiTempOperand (sym->type, 0);
1399 sym->reqv->key = sym->key;
1400 OP_SYMBOL (sym->reqv)->key = sym->key;
1401 OP_SYMBOL (sym->reqv)->isreqv = 1;
1402 OP_SYMBOL (sym->reqv)->islocal = 1;
1403 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1404 SPIL_LOC (sym->reqv) = sym;
1407 if (!IS_AGGREGATE (sym->type))
1411 op->operand.symOperand = sym;
1414 op->isvolatile = isOperandVolatile (op, TRUE);
1415 op->isGlobal = isOperandGlobal (op);
1416 op->isPtr = IS_PTR (operandType (op));
1417 op->isParm = sym->_isparm;
1422 /* itemp = &[_symbol] */
1424 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1425 IC_LEFT (ic)->type = SYMBOL;
1426 IC_LEFT (ic)->operand.symOperand = sym;
1427 IC_LEFT (ic)->key = sym->key;
1428 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1429 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1430 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1433 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1434 if (IS_ARRAY (sym->type))
1436 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1437 IC_RESULT (ic)->isaddr = 0;
1440 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1444 return IC_RESULT (ic);
1447 /*-----------------------------------------------------------------*/
1448 /* operandFromValue - creates an operand from value */
1449 /*-----------------------------------------------------------------*/
1451 operandFromValue (value * val)
1455 /* if this is a symbol then do the symbol thing */
1457 return operandFromSymbol (val->sym);
1459 /* this is not a symbol */
1462 op->operand.valOperand = val;
1463 op->isLiteral = isOperandLiteral (op);
1467 /*-----------------------------------------------------------------*/
1468 /* operandFromLink - operand from typeChain */
1469 /*-----------------------------------------------------------------*/
1471 operandFromLink (sym_link * type)
1475 /* operand from sym_link */
1481 op->operand.typeOperand = copyLinkChain (type);
1485 /*-----------------------------------------------------------------*/
1486 /* operandFromLit - makes an operand from a literal value */
1487 /*-----------------------------------------------------------------*/
1489 operandFromLit (double i)
1491 return operandFromValue (valueFromLit (i));
1494 /*-----------------------------------------------------------------*/
1495 /* operandFromAst - creates an operand from an ast */
1496 /*-----------------------------------------------------------------*/
1498 operandFromAst (ast * tree,int lvl)
1504 /* depending on type do */
1508 return ast2iCode (tree,lvl+1);
1512 return operandFromValue (tree->opval.val);
1516 return operandFromLink (tree->opval.lnk);
1520 /* Just to keep the comiler happy */
1521 return (operand *) 0;
1524 /*-----------------------------------------------------------------*/
1525 /* setOperandType - sets the operand's type to the given type */
1526 /*-----------------------------------------------------------------*/
1528 setOperandType (operand * op, sym_link * type)
1530 /* depending on the type of operand */
1535 op->operand.valOperand->etype =
1536 getSpec (op->operand.valOperand->type =
1537 copyLinkChain (type));
1541 if (op->operand.symOperand->isitmp)
1542 op->operand.symOperand->etype =
1543 getSpec (op->operand.symOperand->type =
1544 copyLinkChain (type));
1546 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1547 "attempt to modify type of source");
1551 op->operand.typeOperand = copyLinkChain (type);
1556 /*-----------------------------------------------------------------*/
1557 /* Get size in byte of ptr need to access an array */
1558 /*-----------------------------------------------------------------*/
1560 getArraySizePtr (operand * op)
1562 sym_link *ltype = operandType(op);
1566 int size = getSize(ltype);
1567 return(IS_GENPTR(ltype)?(size-1):size);
1572 sym_link *letype = getSpec(ltype);
1573 switch (PTR_TYPE (SPEC_OCLS (letype)))
1585 return (GPTRSIZE-1);
1594 /*-----------------------------------------------------------------*/
1595 /* perform "usual unary conversions" */
1596 /*-----------------------------------------------------------------*/
1598 usualUnaryConversions (operand * op)
1600 if (IS_INTEGRAL (operandType (op)))
1602 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1605 return geniCodeCast (INTTYPE, op, TRUE);
1611 /*-----------------------------------------------------------------*/
1612 /* perform "usual binary conversions" */
1613 /*-----------------------------------------------------------------*/
1615 usualBinaryConversions (operand ** op1, operand ** op2)
1618 sym_link *rtype = operandType (*op2);
1619 sym_link *ltype = operandType (*op1);
1621 ctype = computeType (ltype, rtype);
1623 *op1 = geniCodeCast (ctype, *op1, TRUE);
1624 *op2 = geniCodeCast (ctype, *op2, TRUE);
1629 /*-----------------------------------------------------------------*/
1630 /* geniCodeValueAtAddress - generate intermeditate code for value */
1632 /*-----------------------------------------------------------------*/
1634 geniCodeRValue (operand * op, bool force)
1637 sym_link *type = operandType (op);
1638 sym_link *etype = getSpec (type);
1640 /* if this is an array & already */
1641 /* an address then return this */
1642 if (IS_AGGREGATE (type) ||
1643 (IS_PTR (type) && !force && !op->isaddr))
1644 return operandFromOperand (op);
1646 /* if this is not an address then must be */
1647 /* rvalue already so return this one */
1651 /* if this is not a temp symbol then */
1652 if (!IS_ITEMP (op) &&
1654 !IN_FARSPACE (SPEC_OCLS (etype)))
1656 op = operandFromOperand (op);
1661 if (IS_SPEC (type) &&
1662 IS_TRUE_SYMOP (op) &&
1663 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1664 (options.model == MODEL_FLAT24) ))
1666 op = operandFromOperand (op);
1671 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1672 if (IS_PTR (type) && op->isaddr && force)
1675 type = copyLinkChain (type);
1677 IC_RESULT (ic) = newiTempOperand (type, 1);
1678 IC_RESULT (ic)->isaddr = 0;
1680 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1684 return IC_RESULT (ic);
1687 /*-----------------------------------------------------------------*/
1688 /* geniCodeCast - changes the value from one type to another */
1689 /*-----------------------------------------------------------------*/
1691 geniCodeCast (sym_link * type, operand * op, bool implicit)
1695 sym_link *opetype = getSpec (optype = operandType (op));
1699 /* one of them has size zero then error */
1700 if (IS_VOID (optype))
1702 werror (E_CAST_ZERO);
1706 /* if the operand is already the desired type then do nothing */
1707 if (compareType (type, optype) == 1)
1710 /* if this is a literal then just change the type & return */
1711 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1712 return operandFromValue (valCastLiteral (type,
1713 operandLitValue (op)));
1715 /* if casting to/from pointers, do some checking */
1716 if (IS_PTR(type)) { // to a pointer
1717 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1718 if (IS_INTEGRAL(optype)) {
1719 // maybe this is NULL, than it's ok.
1720 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1721 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1722 // no way to set the storage
1723 if (IS_LITERAL(optype)) {
1724 werror(E_LITERAL_GENERIC);
1727 werror(E_NONPTR2_GENPTR);
1730 } else if (implicit) {
1731 werror(W_INTEGRAL2PTR_NOCAST);
1736 // shouldn't do that with float, array or structure unless to void
1737 if (!IS_VOID(getSpec(type)) &&
1738 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1739 werror(E_INCOMPAT_TYPES);
1743 } else { // from a pointer to a pointer
1744 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1745 // if not a pointer to a function
1746 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1747 if (implicit) { // if not to generic, they have to match
1748 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1749 werror(E_INCOMPAT_PTYPES);
1756 } else { // to a non pointer
1757 if (IS_PTR(optype)) { // from a pointer
1758 if (implicit) { // sneaky
1759 if (IS_INTEGRAL(type)) {
1760 werror(W_PTR2INTEGRAL_NOCAST);
1762 } else { // shouldn't do that with float, array or structure
1763 werror(E_INCOMPAT_TYPES);
1770 printFromToType (optype, type);
1773 /* if they are the same size create an assignment */
1774 if (getSize (type) == getSize (optype) &&
1775 !IS_BITFIELD (type) &&
1777 !IS_FLOAT (optype) &&
1778 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1779 (!IS_SPEC (type) && !IS_SPEC (optype))))
1782 ic = newiCode ('=', NULL, op);
1783 IC_RESULT (ic) = newiTempOperand (type, 0);
1784 SPIL_LOC (IC_RESULT (ic)) =
1785 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1786 IC_RESULT (ic)->isaddr = 0;
1790 ic = newiCode (CAST, operandFromLink (type),
1791 geniCodeRValue (op, FALSE));
1793 IC_RESULT (ic) = newiTempOperand (type, 0);
1796 /* preserve the storage class & output class */
1797 /* of the original variable */
1798 restype = getSpec (operandType (IC_RESULT (ic)));
1799 if (!IS_LITERAL(opetype))
1800 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1801 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1804 return IC_RESULT (ic);
1807 /*-----------------------------------------------------------------*/
1808 /* geniCodeLabel - will create a Label */
1809 /*-----------------------------------------------------------------*/
1811 geniCodeLabel (symbol * label)
1815 ic = newiCodeLabelGoto (LABEL, label);
1819 /*-----------------------------------------------------------------*/
1820 /* geniCodeGoto - will create a Goto */
1821 /*-----------------------------------------------------------------*/
1823 geniCodeGoto (symbol * label)
1827 ic = newiCodeLabelGoto (GOTO, label);
1831 /*-----------------------------------------------------------------*/
1832 /* geniCodeMultiply - gen intermediate code for multiplication */
1833 /*-----------------------------------------------------------------*/
1835 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1842 /* if they are both literal then we know the result */
1843 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1844 return operandFromValue (valMult (left->operand.valOperand,
1845 right->operand.valOperand));
1847 if (IS_LITERAL(retype)) {
1848 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1851 resType = usualBinaryConversions (&left, &right);
1853 rtype = operandType (right);
1854 retype = getSpec (rtype);
1855 ltype = operandType (left);
1856 letype = getSpec (ltype);
1860 SPEC_NOUN(getSpec(resType))=V_INT;
1863 /* if the right is a literal & power of 2 */
1864 /* then make it a left shift */
1865 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1866 efficient in most cases than 2 bytes result = 2 bytes << literal
1867 if port has 1 byte muldiv */
1868 if (p2 && !IS_FLOAT (letype) &&
1869 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1870 (port->support.muldiv == 1)))
1872 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1874 /* LEFT_OP need same size for left and result, */
1875 left = geniCodeCast (resType, left, TRUE);
1876 ltype = operandType (left);
1878 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1882 ic = newiCode ('*', left, right); /* normal multiplication */
1883 /* if the size left or right > 1 then support routine */
1884 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1888 IC_RESULT (ic) = newiTempOperand (resType, 1);
1891 return IC_RESULT (ic);
1894 /*-----------------------------------------------------------------*/
1895 /* geniCodeDivision - gen intermediate code for division */
1896 /*-----------------------------------------------------------------*/
1898 geniCodeDivision (operand * left, operand * right)
1903 sym_link *rtype = operandType (right);
1904 sym_link *retype = getSpec (rtype);
1905 sym_link *ltype = operandType (left);
1906 sym_link *letype = getSpec (ltype);
1908 resType = usualBinaryConversions (&left, &right);
1910 /* if the right is a literal & power of 2
1911 and left is unsigned then make it a
1913 if (IS_LITERAL (retype) &&
1914 !IS_FLOAT (letype) &&
1915 SPEC_USIGN(letype) &&
1916 (p2 = powof2 ((unsigned long)
1917 floatFromVal (right->operand.valOperand)))) {
1918 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1922 ic = newiCode ('/', left, right); /* normal division */
1923 /* if the size left or right > 1 then support routine */
1924 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1927 IC_RESULT (ic) = newiTempOperand (resType, 0);
1930 return IC_RESULT (ic);
1932 /*-----------------------------------------------------------------*/
1933 /* geniCodeModulus - gen intermediate code for modulus */
1934 /*-----------------------------------------------------------------*/
1936 geniCodeModulus (operand * left, operand * right)
1942 /* if they are both literal then we know the result */
1943 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1944 return operandFromValue (valMod (left->operand.valOperand,
1945 right->operand.valOperand));
1947 resType = usualBinaryConversions (&left, &right);
1949 /* now they are the same size */
1950 ic = newiCode ('%', left, right);
1952 /* if the size left or right > 1 then support routine */
1953 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1955 IC_RESULT (ic) = newiTempOperand (resType, 0);
1958 return IC_RESULT (ic);
1961 /*-----------------------------------------------------------------*/
1962 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1963 /*-----------------------------------------------------------------*/
1965 geniCodePtrPtrSubtract (operand * left, operand * right)
1971 /* if they are both literals then */
1972 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1974 result = operandFromValue (valMinus (left->operand.valOperand,
1975 right->operand.valOperand));
1979 ic = newiCode ('-', left, right);
1981 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1985 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1989 // should we really do this? is this ANSI?
1990 return geniCodeDivision (result,
1991 operandFromLit (getSize (ltype->next)));
1994 /*-----------------------------------------------------------------*/
1995 /* geniCodeSubtract - generates code for subtraction */
1996 /*-----------------------------------------------------------------*/
1998 geniCodeSubtract (operand * left, operand * right)
2005 /* if they both pointers then */
2006 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2007 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2008 return geniCodePtrPtrSubtract (left, right);
2010 /* if they are both literal then we know the result */
2011 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2012 && left->isLiteral && right->isLiteral)
2013 return operandFromValue (valMinus (left->operand.valOperand,
2014 right->operand.valOperand));
2016 /* if left is an array or pointer */
2017 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2019 isarray = left->isaddr;
2020 right = geniCodeMultiply (right,
2021 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2022 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2025 { /* make them the same size */
2026 resType = usualBinaryConversions (&left, &right);
2029 ic = newiCode ('-', left, right);
2031 IC_RESULT (ic) = newiTempOperand (resType, 1);
2032 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2034 /* if left or right is a float */
2035 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2039 return IC_RESULT (ic);
2042 /*-----------------------------------------------------------------*/
2043 /* geniCodeAdd - generates iCode for addition */
2044 /*-----------------------------------------------------------------*/
2046 geniCodeAdd (operand * left, operand * right, int lvl)
2055 /* if left is an array then array access */
2056 if (IS_ARRAY (ltype))
2057 return geniCodeArray (left, right,lvl);
2060 /* if the right side is LITERAL zero */
2061 /* return the left side */
2062 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2065 /* if left is literal zero return right */
2066 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2069 /* if left is a pointer then size */
2070 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2072 isarray = left->isaddr;
2073 // there is no need to multiply with 1
2074 if (getSize(ltype->next)!=1) {
2075 size = operandFromLit (getSize (ltype->next));
2076 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2078 resType = copyLinkChain (ltype);
2081 { // make them the same size
2082 resType = usualBinaryConversions (&left, &right);
2085 /* if they are both literals then we know */
2086 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2087 && left->isLiteral && right->isLiteral)
2088 return operandFromValue (valPlus (valFromType (letype),
2089 valFromType (retype)));
2091 ic = newiCode ('+', left, right);
2093 IC_RESULT (ic) = newiTempOperand (resType, 1);
2094 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2096 /* if left or right is a float then support
2098 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2103 return IC_RESULT (ic);
2107 /*-----------------------------------------------------------------*/
2108 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2109 /*-----------------------------------------------------------------*/
2111 aggrToPtr (sym_link * type, bool force)
2117 if (IS_PTR (type) && !force)
2120 etype = getSpec (type);
2126 /* if the output class is code */
2127 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2128 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2130 /* if the variable was declared a constant */
2131 /* then the pointer points to a constant */
2132 if (IS_CONSTANT (etype))
2133 DCL_PTR_CONST (ptype) = 1;
2135 /* the variable was volatile then pointer to volatile */
2136 if (IS_VOLATILE (etype))
2137 DCL_PTR_VOLATILE (ptype) = 1;
2139 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodeArray2Ptr - array to pointer */
2147 /*-----------------------------------------------------------------*/
2149 geniCodeArray2Ptr (operand * op)
2151 sym_link *optype = operandType (op);
2152 sym_link *opetype = getSpec (optype);
2155 /* set the pointer depending on the storage class */
2156 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2157 DCL_PTR_CONST (optype) = port->mem.code_ro;
2159 /* if the variable was declared a constant */
2160 /* then the pointer points to a constant */
2161 if (IS_CONSTANT (opetype))
2162 DCL_PTR_CONST (optype) = 1;
2164 /* the variable was volatile then pointer to volatile */
2165 if (IS_VOLATILE (opetype))
2166 DCL_PTR_VOLATILE (optype) = 1;
2168 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2176 /*-----------------------------------------------------------------*/
2177 /* geniCodeArray - array access */
2178 /*-----------------------------------------------------------------*/
2180 geniCodeArray (operand * left, operand * right,int lvl)
2183 sym_link *ltype = operandType (left);
2187 if (IS_PTR (ltype->next) && left->isaddr)
2189 left = geniCodeRValue (left, FALSE);
2191 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2194 right = geniCodeMultiply (right,
2195 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2197 /* we can check for limits here */
2198 if (isOperandLiteral (right) &&
2201 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2203 werror (E_ARRAY_BOUND);
2204 right = operandFromLit (0);
2207 ic = newiCode ('+', left, right);
2209 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2210 !IS_AGGREGATE (ltype->next) &&
2211 !IS_PTR (ltype->next))
2212 ? ltype : ltype->next), 0);
2214 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2216 return IC_RESULT (ic);
2219 /*-----------------------------------------------------------------*/
2220 /* geniCodeStruct - generates intermediate code for structres */
2221 /*-----------------------------------------------------------------*/
2223 geniCodeStruct (operand * left, operand * right, bool islval)
2226 sym_link *type = operandType (left);
2227 sym_link *etype = getSpec (type);
2229 symbol *element = getStructElement (SPEC_STRUCT (etype),
2230 right->operand.symOperand);
2232 wassert(IS_SYMOP(right));
2234 /* add the offset */
2235 ic = newiCode ('+', left, operandFromLit (element->offset));
2237 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2239 /* preserve the storage & output class of the struct */
2240 /* as well as the volatile attribute */
2241 retype = getSpec (operandType (IC_RESULT (ic)));
2242 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2243 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2244 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2246 if (IS_PTR (element->type))
2247 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2249 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2253 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2256 /*-----------------------------------------------------------------*/
2257 /* geniCodePostInc - generate int code for Post increment */
2258 /*-----------------------------------------------------------------*/
2260 geniCodePostInc (operand * op)
2264 sym_link *optype = operandType (op);
2266 operand *rv = (IS_ITEMP (op) ?
2267 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2269 sym_link *rvtype = operandType (rv);
2272 /* if this is not an address we have trouble */
2275 werror (E_LVALUE_REQUIRED, "++");
2279 rOp = newiTempOperand (rvtype, 0);
2280 OP_SYMBOL(rOp)->noSpilLoc = 1;
2283 OP_SYMBOL(rv)->noSpilLoc = 1;
2285 geniCodeAssign (rOp, rv, 0);
2287 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2288 if (IS_FLOAT (rvtype))
2289 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2291 ic = newiCode ('+', rv, operandFromLit (size));
2293 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2296 geniCodeAssign (op, result, 0);
2302 /*-----------------------------------------------------------------*/
2303 /* geniCodePreInc - generate code for preIncrement */
2304 /*-----------------------------------------------------------------*/
2306 geniCodePreInc (operand * op)
2309 sym_link *optype = operandType (op);
2310 operand *rop = (IS_ITEMP (op) ?
2311 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2313 sym_link *roptype = operandType (rop);
2319 werror (E_LVALUE_REQUIRED, "++");
2324 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2325 if (IS_FLOAT (roptype))
2326 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2328 ic = newiCode ('+', rop, operandFromLit (size));
2329 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2333 return geniCodeAssign (op, result, 0);
2336 /*-----------------------------------------------------------------*/
2337 /* geniCodePostDec - generates code for Post decrement */
2338 /*-----------------------------------------------------------------*/
2340 geniCodePostDec (operand * op)
2344 sym_link *optype = operandType (op);
2346 operand *rv = (IS_ITEMP (op) ?
2347 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2349 sym_link *rvtype = operandType (rv);
2352 /* if this is not an address we have trouble */
2355 werror (E_LVALUE_REQUIRED, "--");
2359 rOp = newiTempOperand (rvtype, 0);
2360 OP_SYMBOL(rOp)->noSpilLoc = 1;
2363 OP_SYMBOL(rv)->noSpilLoc = 1;
2365 geniCodeAssign (rOp, rv, 0);
2367 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2368 if (IS_FLOAT (rvtype))
2369 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2371 ic = newiCode ('-', rv, operandFromLit (size));
2373 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2376 geniCodeAssign (op, result, 0);
2382 /*-----------------------------------------------------------------*/
2383 /* geniCodePreDec - generate code for pre decrement */
2384 /*-----------------------------------------------------------------*/
2386 geniCodePreDec (operand * op)
2389 sym_link *optype = operandType (op);
2390 operand *rop = (IS_ITEMP (op) ?
2391 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2393 sym_link *roptype = operandType (rop);
2399 werror (E_LVALUE_REQUIRED, "--");
2404 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2405 if (IS_FLOAT (roptype))
2406 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2408 ic = newiCode ('-', rop, operandFromLit (size));
2409 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2413 return geniCodeAssign (op, result, 0);
2417 /*-----------------------------------------------------------------*/
2418 /* geniCodeBitwise - gen int code for bitWise operators */
2419 /*-----------------------------------------------------------------*/
2421 geniCodeBitwise (operand * left, operand * right,
2422 int oper, sym_link * resType)
2426 left = geniCodeCast (resType, left, TRUE);
2427 right = geniCodeCast (resType, right, TRUE);
2429 ic = newiCode (oper, left, right);
2430 IC_RESULT (ic) = newiTempOperand (resType, 0);
2433 return IC_RESULT (ic);
2436 /*-----------------------------------------------------------------*/
2437 /* geniCodeAddressOf - gens icode for '&' address of operator */
2438 /*-----------------------------------------------------------------*/
2440 geniCodeAddressOf (operand * op)
2444 sym_link *optype = operandType (op);
2445 sym_link *opetype = getSpec (optype);
2447 /* lvalue check already done in decorateType */
2448 /* this must be a lvalue */
2449 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2450 /* werror (E_LVALUE_REQUIRED,"&"); */
2455 p->class = DECLARATOR;
2458 /* set the pointer depending on the storage class */
2459 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2460 DCL_PTR_CONST (p) = port->mem.code_ro;
2462 /* make sure we preserve the const & volatile */
2463 if (IS_CONSTANT (opetype))
2464 DCL_PTR_CONST (p) = 1;
2466 if (IS_VOLATILE (opetype))
2467 DCL_PTR_VOLATILE (p) = 1;
2469 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2473 p->next = copyLinkChain (optype);
2475 /* if already a temp */
2478 setOperandType (op, p);
2483 /* other wise make this of the type coming in */
2484 ic = newiCode (ADDRESS_OF, op, NULL);
2485 IC_RESULT (ic) = newiTempOperand (p, 1);
2486 IC_RESULT (ic)->isaddr = 0;
2488 return IC_RESULT (ic);
2490 /*-----------------------------------------------------------------*/
2491 /* setOClass - sets the output class depending on the pointer type */
2492 /*-----------------------------------------------------------------*/
2494 setOClass (sym_link * ptr, sym_link * spec)
2496 switch (DCL_TYPE (ptr))
2499 SPEC_OCLS (spec) = data;
2503 SPEC_OCLS (spec) = generic;
2507 SPEC_OCLS (spec) = xdata;
2511 SPEC_OCLS (spec) = code;
2515 SPEC_OCLS (spec) = idata;
2519 SPEC_OCLS (spec) = xstack;
2523 SPEC_OCLS (spec) = eeprom;
2532 /*-----------------------------------------------------------------*/
2533 /* geniCodeDerefPtr - dereference pointer with '*' */
2534 /*-----------------------------------------------------------------*/
2536 geniCodeDerefPtr (operand * op,int lvl)
2538 sym_link *rtype, *retype;
2539 sym_link *optype = operandType (op);
2541 /* if this is a pointer then generate the rvalue */
2542 if (IS_PTR (optype))
2544 if (IS_TRUE_SYMOP (op))
2547 op = geniCodeRValue (op, TRUE);
2550 op = geniCodeRValue (op, TRUE);
2553 /* now get rid of the pointer part */
2554 if (isLvaluereq(lvl) && IS_ITEMP (op))
2556 retype = getSpec (rtype = copyLinkChain (optype));
2560 retype = getSpec (rtype = copyLinkChain (optype->next));
2563 /* if this is a pointer then outputclass needs 2b updated */
2564 if (IS_PTR (optype))
2565 setOClass (optype, retype);
2567 op->isGptr = IS_GENPTR (optype);
2569 /* if the pointer was declared as a constant */
2570 /* then we cannot allow assignment to the derefed */
2571 if (IS_PTR_CONST (optype))
2572 SPEC_CONST (retype) = 1;
2574 op->isaddr = (IS_PTR (rtype) ||
2575 IS_STRUCT (rtype) ||
2580 if (!isLvaluereq(lvl))
2581 op = geniCodeRValue (op, TRUE);
2583 setOperandType (op, rtype);
2588 /*-----------------------------------------------------------------*/
2589 /* geniCodeUnaryMinus - does a unary minus of the operand */
2590 /*-----------------------------------------------------------------*/
2592 geniCodeUnaryMinus (operand * op)
2595 sym_link *optype = operandType (op);
2597 if (IS_LITERAL (optype))
2598 return operandFromLit (-floatFromVal (op->operand.valOperand));
2600 ic = newiCode (UNARYMINUS, op, NULL);
2601 IC_RESULT (ic) = newiTempOperand (optype, 0);
2603 return IC_RESULT (ic);
2606 /*-----------------------------------------------------------------*/
2607 /* geniCodeLeftShift - gen i code for left shift */
2608 /*-----------------------------------------------------------------*/
2610 geniCodeLeftShift (operand * left, operand * right)
2614 ic = newiCode (LEFT_OP, left, right);
2615 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2617 return IC_RESULT (ic);
2620 /*-----------------------------------------------------------------*/
2621 /* geniCodeRightShift - gen i code for right shift */
2622 /*-----------------------------------------------------------------*/
2624 geniCodeRightShift (operand * left, operand * right)
2628 ic = newiCode (RIGHT_OP, left, right);
2629 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2631 return IC_RESULT (ic);
2634 /*-----------------------------------------------------------------*/
2635 /* geniCodeLogic- logic code */
2636 /*-----------------------------------------------------------------*/
2638 geniCodeLogic (operand * left, operand * right, int op)
2642 sym_link *rtype = operandType (right);
2643 sym_link *ltype = operandType (left);
2645 /* left is integral type and right is literal then
2646 check if the literal value is within bounds */
2647 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2649 checkConstantRange(ltype,
2650 OP_VALUE(right), "compare operation", 1);
2653 ctype = usualBinaryConversions (&left, &right);
2655 ic = newiCode (op, left, right);
2656 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2658 /* if comparing float
2659 and not a '==' || '!=' || '&&' || '||' (these
2661 if (IS_FLOAT(ctype) &&
2669 return IC_RESULT (ic);
2672 /*-----------------------------------------------------------------*/
2673 /* geniCodeUnary - for a a generic unary operation */
2674 /*-----------------------------------------------------------------*/
2676 geniCodeUnary (operand * op, int oper)
2678 iCode *ic = newiCode (oper, op, NULL);
2680 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2682 return IC_RESULT (ic);
2685 /*-----------------------------------------------------------------*/
2686 /* geniCodeConditional - geniCode for '?' ':' operation */
2687 /*-----------------------------------------------------------------*/
2689 geniCodeConditional (ast * tree,int lvl)
2692 symbol *falseLabel = newiTempLabel (NULL);
2693 symbol *exitLabel = newiTempLabel (NULL);
2694 operand *cond = ast2iCode (tree->left,lvl+1);
2695 operand *true, *false, *result;
2697 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2701 true = ast2iCode (tree->right->left,lvl+1);
2703 /* move the value to a new Operand */
2704 result = newiTempOperand (tree->right->ftype, 0);
2705 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2707 /* generate an unconditional goto */
2708 geniCodeGoto (exitLabel);
2710 /* now for the right side */
2711 geniCodeLabel (falseLabel);
2713 false = ast2iCode (tree->right->right,lvl+1);
2714 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2716 /* create the exit label */
2717 geniCodeLabel (exitLabel);
2722 /*-----------------------------------------------------------------*/
2723 /* geniCodeAssign - generate code for assignment */
2724 /*-----------------------------------------------------------------*/
2726 geniCodeAssign (operand * left, operand * right, int nosupdate)
2729 sym_link *ltype = operandType (left);
2730 sym_link *rtype = operandType (right);
2732 if (!left->isaddr && !IS_ITEMP (left))
2734 werror (E_LVALUE_REQUIRED, "assignment");
2738 /* left is integral type and right is literal then
2739 check if the literal value is within bounds */
2740 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2742 checkConstantRange(ltype,
2743 OP_VALUE(right), "= operation", 0);
2746 /* if the left & right type don't exactly match */
2747 /* if pointer set then make sure the check is
2748 done with the type & not the pointer */
2749 /* then cast rights type to left */
2751 /* first check the type for pointer assignement */
2752 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2753 compareType (ltype, rtype) <= 0)
2755 if (compareType (ltype->next, rtype) < 0)
2756 right = geniCodeCast (ltype->next, right, TRUE);
2758 else if (compareType (ltype, rtype) < 0)
2759 right = geniCodeCast (ltype, right, TRUE);
2761 /* if left is a true symbol & ! volatile
2762 create an assignment to temporary for
2763 the right & then assign this temporary
2764 to the symbol this is SSA . isn't it simple
2765 and folks have published mountains of paper on it */
2766 if (IS_TRUE_SYMOP (left) &&
2767 !isOperandVolatile (left, FALSE) &&
2768 isOperandGlobal (left))
2772 if (IS_TRUE_SYMOP (right))
2773 sym = OP_SYMBOL (right);
2774 ic = newiCode ('=', NULL, right);
2775 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2776 SPIL_LOC (right) = sym;
2780 ic = newiCode ('=', NULL, right);
2781 IC_RESULT (ic) = left;
2784 /* if left isgptr flag is set then support
2785 routine will be required */
2789 ic->nosupdate = nosupdate;
2793 /*-----------------------------------------------------------------*/
2794 /* geniCodeSEParms - generate code for side effecting fcalls */
2795 /*-----------------------------------------------------------------*/
2797 geniCodeSEParms (ast * parms,int lvl)
2802 if (parms->type == EX_OP && parms->opval.op == PARAM)
2804 geniCodeSEParms (parms->left,lvl);
2805 geniCodeSEParms (parms->right,lvl);
2809 /* hack don't like this but too lazy to think of
2811 if (IS_ADDRESS_OF_OP (parms))
2812 parms->left->lvalue = 1;
2814 if (IS_CAST_OP (parms) &&
2815 IS_PTR (parms->ftype) &&
2816 IS_ADDRESS_OF_OP (parms->right))
2817 parms->right->left->lvalue = 1;
2819 parms->opval.oprnd =
2820 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2822 parms->type = EX_OPERAND;
2823 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2824 SPEC_ARGREG(parms->ftype);
2827 /*-----------------------------------------------------------------*/
2828 /* geniCodeParms - generates parameters */
2829 /*-----------------------------------------------------------------*/
2831 geniCodeParms (ast * parms, value *argVals, int *stack,
2832 sym_link * fetype, symbol * func,int lvl)
2840 if (argVals==NULL) {
2842 argVals=FUNC_ARGS(func->type);
2845 /* if this is a param node then do the left & right */
2846 if (parms->type == EX_OP && parms->opval.op == PARAM)
2848 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2849 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2853 /* get the parameter value */
2854 if (parms->type == EX_OPERAND)
2855 pval = parms->opval.oprnd;
2858 /* maybe this else should go away ?? */
2859 /* hack don't like this but too lazy to think of
2861 if (IS_ADDRESS_OF_OP (parms))
2862 parms->left->lvalue = 1;
2864 if (IS_CAST_OP (parms) &&
2865 IS_PTR (parms->ftype) &&
2866 IS_ADDRESS_OF_OP (parms->right))
2867 parms->right->left->lvalue = 1;
2869 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2872 /* if register parm then make it a send */
2873 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2874 IFFUNC_ISBUILTIN(func->type))
2876 ic = newiCode (SEND, pval, NULL);
2877 ic->argreg = SPEC_ARGREG(parms->etype);
2878 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2883 /* now decide whether to push or assign */
2884 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2888 operand *top = operandFromSymbol (argVals->sym);
2889 /* clear useDef and other bitVectors */
2890 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2891 geniCodeAssign (top, pval, 1);
2895 sym_link *p = operandType (pval);
2897 ic = newiCode (IPUSH, pval, NULL);
2899 /* update the stack adjustment */
2900 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2905 argVals=argVals->next;
2909 /*-----------------------------------------------------------------*/
2910 /* geniCodeCall - generates temp code for calling */
2911 /*-----------------------------------------------------------------*/
2913 geniCodeCall (operand * left, ast * parms,int lvl)
2917 sym_link *type, *etype;
2920 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2921 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2922 werror (E_FUNCTION_EXPECTED);
2926 /* take care of parameters with side-effecting
2927 function calls in them, this is required to take care
2928 of overlaying function parameters */
2929 geniCodeSEParms (parms,lvl);
2931 /* first the parameters */
2932 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2934 /* now call : if symbol then pcall */
2935 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2936 ic = newiCode (PCALL, left, NULL);
2938 ic = newiCode (CALL, left, NULL);
2941 type = copyLinkChain (operandType (left)->next);
2942 etype = getSpec (type);
2943 SPEC_EXTR (etype) = 0;
2944 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2948 /* stack adjustment after call */
2949 ic->parmBytes = stack;
2954 /*-----------------------------------------------------------------*/
2955 /* geniCodeReceive - generate intermediate code for "receive" */
2956 /*-----------------------------------------------------------------*/
2958 geniCodeReceive (value * args)
2960 /* for all arguments that are passed in registers */
2964 if (IS_REGPARM (args->etype))
2966 operand *opr = operandFromValue (args);
2968 symbol *sym = OP_SYMBOL (opr);
2971 /* we will use it after all optimizations
2972 and before liveRange calculation */
2973 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2976 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2977 options.stackAuto == 0 &&
2978 (!(options.model == MODEL_FLAT24)) )
2983 opl = newiTempOperand (args->type, 0);
2985 sym->reqv->key = sym->key;
2986 OP_SYMBOL (sym->reqv)->key = sym->key;
2987 OP_SYMBOL (sym->reqv)->isreqv = 1;
2988 OP_SYMBOL (sym->reqv)->islocal = 0;
2989 SPIL_LOC (sym->reqv) = sym;
2993 ic = newiCode (RECEIVE, NULL, NULL);
2994 ic->argreg = SPEC_ARGREG(args->etype);
2996 currFunc->recvSize = getSize (sym->type);
2999 IC_RESULT (ic) = opr;
3007 /*-----------------------------------------------------------------*/
3008 /* geniCodeFunctionBody - create the function body */
3009 /*-----------------------------------------------------------------*/
3011 geniCodeFunctionBody (ast * tree,int lvl)
3018 /* reset the auto generation */
3024 func = ast2iCode (tree->left,lvl+1);
3025 fetype = getSpec (operandType (func));
3027 savelineno = lineno;
3028 lineno = OP_SYMBOL (func)->lineDef;
3029 /* create an entry label */
3030 geniCodeLabel (entryLabel);
3031 lineno = savelineno;
3033 /* create a proc icode */
3034 ic = newiCode (FUNCTION, func, NULL);
3035 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3039 /* for all parameters that are passed
3040 on registers add a "receive" */
3041 geniCodeReceive (tree->values.args);
3043 /* generate code for the body */
3044 ast2iCode (tree->right,lvl+1);
3046 /* create a label for return */
3047 geniCodeLabel (returnLabel);
3049 /* now generate the end proc */
3050 ic = newiCode (ENDFUNCTION, func, NULL);
3055 /*-----------------------------------------------------------------*/
3056 /* geniCodeReturn - gen icode for 'return' statement */
3057 /*-----------------------------------------------------------------*/
3059 geniCodeReturn (operand * op)
3063 /* if the operand is present force an rvalue */
3065 op = geniCodeRValue (op, FALSE);
3067 ic = newiCode (RETURN, op, NULL);
3071 /*-----------------------------------------------------------------*/
3072 /* geniCodeIfx - generates code for extended if statement */
3073 /*-----------------------------------------------------------------*/
3075 geniCodeIfx (ast * tree,int lvl)
3078 operand *condition = ast2iCode (tree->left,lvl+1);
3081 /* if condition is null then exit */
3085 condition = geniCodeRValue (condition, FALSE);
3087 cetype = getSpec (operandType (condition));
3088 /* if the condition is a literal */
3089 if (IS_LITERAL (cetype))
3091 if (floatFromVal (condition->operand.valOperand))
3093 if (tree->trueLabel)
3094 geniCodeGoto (tree->trueLabel);
3100 if (tree->falseLabel)
3101 geniCodeGoto (tree->falseLabel);
3108 if (tree->trueLabel)
3110 ic = newiCodeCondition (condition,
3115 if (tree->falseLabel)
3116 geniCodeGoto (tree->falseLabel);
3120 ic = newiCodeCondition (condition,
3127 ast2iCode (tree->right,lvl+1);
3130 /*-----------------------------------------------------------------*/
3131 /* geniCodeJumpTable - tries to create a jump table for switch */
3132 /*-----------------------------------------------------------------*/
3134 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3136 int min = 0, max = 0, t, cnt = 0;
3143 if (!tree || !caseVals)
3146 /* the criteria for creating a jump table is */
3147 /* all integer numbers between the maximum & minimum must */
3148 /* be present , the maximum value should not exceed 255 */
3149 min = max = (int) floatFromVal (vch = caseVals);
3150 SNPRINTF (buffer, sizeof(buffer),
3152 tree->values.switchVals.swNum,
3154 addSet (&labels, newiTempLabel (buffer));
3156 /* if there is only one case value then no need */
3157 if (!(vch = vch->next))
3162 if (((t = (int) floatFromVal (vch)) - max) != 1)
3164 SNPRINTF (buffer, sizeof(buffer),
3166 tree->values.switchVals.swNum,
3168 addSet (&labels, newiTempLabel (buffer));
3174 /* if the number of case statements <= 2 then */
3175 /* it is not economical to create the jump table */
3176 /* since two compares are needed for boundary conditions */
3177 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3180 if (tree->values.switchVals.swDefault)
3182 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3186 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3190 falseLabel = newiTempLabel (buffer);
3192 /* so we can create a jumptable */
3193 /* first we rule out the boundary conditions */
3194 /* if only optimization says so */
3195 if (!optimize.noJTabBoundary)
3197 sym_link *cetype = getSpec (operandType (cond));
3198 /* no need to check the lower bound if
3199 the condition is unsigned & minimum value is zero */
3200 if (!(min == 0 && SPEC_USIGN (cetype)))
3202 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3203 ic = newiCodeCondition (boundary, falseLabel, NULL);
3207 /* now for upper bounds */
3208 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3209 ic = newiCodeCondition (boundary, falseLabel, NULL);
3213 /* if the min is not zero then we no make it zero */
3216 cond = geniCodeSubtract (cond, operandFromLit (min));
3217 setOperandType (cond, UCHARTYPE);
3220 /* now create the jumptable */
3221 ic = newiCode (JUMPTABLE, NULL, NULL);
3222 IC_JTCOND (ic) = cond;
3223 IC_JTLABELS (ic) = labels;
3228 /*-----------------------------------------------------------------*/
3229 /* geniCodeSwitch - changes a switch to a if statement */
3230 /*-----------------------------------------------------------------*/
3232 geniCodeSwitch (ast * tree,int lvl)
3235 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3236 value *caseVals = tree->values.switchVals.swVals;
3237 symbol *trueLabel, *falseLabel;
3239 /* if we can make this a jump table */
3240 if (geniCodeJumpTable (cond, caseVals, tree))
3241 goto jumpTable; /* no need for the comparison */
3243 /* for the cases defined do */
3247 operand *compare = geniCodeLogic (cond,
3248 operandFromValue (caseVals),
3251 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3252 tree->values.switchVals.swNum,
3253 (int) floatFromVal (caseVals));
3254 trueLabel = newiTempLabel (buffer);
3256 ic = newiCodeCondition (compare, trueLabel, NULL);
3258 caseVals = caseVals->next;
3263 /* if default is present then goto break else break */
3264 if (tree->values.switchVals.swDefault)
3266 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3270 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3273 falseLabel = newiTempLabel (buffer);
3274 geniCodeGoto (falseLabel);
3277 ast2iCode (tree->right,lvl+1);
3280 /*-----------------------------------------------------------------*/
3281 /* geniCodeInline - intermediate code for inline assembler */
3282 /*-----------------------------------------------------------------*/
3284 geniCodeInline (ast * tree)
3288 ic = newiCode (INLINEASM, NULL, NULL);
3289 IC_INLINE (ic) = tree->values.inlineasm;
3293 /*-----------------------------------------------------------------*/
3294 /* geniCodeArrayInit - intermediate code for array initializer */
3295 /*-----------------------------------------------------------------*/
3297 geniCodeArrayInit (ast * tree, operand *array)
3301 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3302 ic = newiCode (ARRAYINIT, array, NULL);
3303 IC_ARRAYILIST (ic) = tree->values.constlist;
3305 operand *left=newOperand(), *right=newOperand();
3306 left->type=right->type=SYMBOL;
3307 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3308 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3309 ic = newiCode (ARRAYINIT, left, right);
3314 /*-----------------------------------------------------------------*/
3315 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3316 /* particular case. Ie : assigning or dereferencing array or ptr */
3317 /*-----------------------------------------------------------------*/
3318 set * lvaluereqSet = NULL;
3319 typedef struct lvalItem
3326 /*-----------------------------------------------------------------*/
3327 /* addLvaluereq - add a flag for lvalreq for current ast level */
3328 /*-----------------------------------------------------------------*/
3329 void addLvaluereq(int lvl)
3331 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3334 addSetHead(&lvaluereqSet,lpItem);
3337 /*-----------------------------------------------------------------*/
3338 /* delLvaluereq - del a flag for lvalreq for current ast level */
3339 /*-----------------------------------------------------------------*/
3343 lpItem = getSet(&lvaluereqSet);
3344 if(lpItem) Safe_free(lpItem);
3346 /*-----------------------------------------------------------------*/
3347 /* clearLvaluereq - clear lvalreq flag */
3348 /*-----------------------------------------------------------------*/
3349 void clearLvaluereq()
3352 lpItem = peekSet(lvaluereqSet);
3353 if(lpItem) lpItem->req = 0;
3355 /*-----------------------------------------------------------------*/
3356 /* getLvaluereq - get the last lvalreq level */
3357 /*-----------------------------------------------------------------*/
3358 int getLvaluereqLvl()
3361 lpItem = peekSet(lvaluereqSet);
3362 if(lpItem) return lpItem->lvl;
3365 /*-----------------------------------------------------------------*/
3366 /* isLvaluereq - is lvalreq valid for this level ? */
3367 /*-----------------------------------------------------------------*/
3368 int isLvaluereq(int lvl)
3371 lpItem = peekSet(lvaluereqSet);
3372 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3376 /*-----------------------------------------------------------------*/
3377 /* ast2iCode - creates an icodeList from an ast */
3378 /*-----------------------------------------------------------------*/
3380 ast2iCode (ast * tree,int lvl)
3382 operand *left = NULL;
3383 operand *right = NULL;
3387 /* set the global variables for filename & line number */
3389 filename = tree->filename;
3391 lineno = tree->lineno;
3393 block = tree->block;
3395 scopeLevel = tree->level;
3397 if (tree->type == EX_VALUE)
3398 return operandFromValue (tree->opval.val);
3400 if (tree->type == EX_LINK)
3401 return operandFromLink (tree->opval.lnk);
3403 /* if we find a nullop */
3404 if (tree->type == EX_OP &&
3405 (tree->opval.op == NULLOP ||
3406 tree->opval.op == BLOCK))
3408 ast2iCode (tree->left,lvl+1);
3409 ast2iCode (tree->right,lvl+1);
3413 /* special cases for not evaluating */
3414 if (tree->opval.op != ':' &&
3415 tree->opval.op != '?' &&
3416 tree->opval.op != CALL &&
3417 tree->opval.op != IFX &&
3418 tree->opval.op != LABEL &&
3419 tree->opval.op != GOTO &&
3420 tree->opval.op != SWITCH &&
3421 tree->opval.op != FUNCTION &&
3422 tree->opval.op != INLINEASM)
3425 if (IS_ASSIGN_OP (tree->opval.op) ||
3426 IS_DEREF_OP (tree) ||
3427 (tree->opval.op == '&' && !tree->right) ||
3428 tree->opval.op == PTR_OP)
3431 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3432 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3435 left = operandFromAst (tree->left,lvl);
3437 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3438 left = geniCodeRValue (left, TRUE);
3442 left = operandFromAst (tree->left,lvl);
3444 if (tree->opval.op == INC_OP ||
3445 tree->opval.op == DEC_OP)
3448 right = operandFromAst (tree->right,lvl);
3453 right = operandFromAst (tree->right,lvl);
3457 /* now depending on the type of operand */
3458 /* this will be a biggy */
3459 switch (tree->opval.op)
3462 case '[': /* array operation */
3464 //sym_link *ltype = operandType (left);
3465 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3466 left = geniCodeRValue (left, FALSE);
3467 right = geniCodeRValue (right, TRUE);
3470 return geniCodeArray (left, right,lvl);
3472 case '.': /* structure dereference */
3473 if (IS_PTR (operandType (left)))
3474 left = geniCodeRValue (left, TRUE);
3476 left = geniCodeRValue (left, FALSE);
3478 return geniCodeStruct (left, right, tree->lvalue);
3480 case PTR_OP: /* structure pointer dereference */
3483 pType = operandType (left);
3484 left = geniCodeRValue (left, TRUE);
3486 setOClass (pType, getSpec (operandType (left)));
3489 return geniCodeStruct (left, right, tree->lvalue);
3491 case INC_OP: /* increment operator */
3493 return geniCodePostInc (left);
3495 return geniCodePreInc (right);
3497 case DEC_OP: /* decrement operator */
3499 return geniCodePostDec (left);
3501 return geniCodePreDec (right);
3503 case '&': /* bitwise and or address of operator */
3505 { /* this is a bitwise operator */
3506 left = geniCodeRValue (left, FALSE);
3507 right = geniCodeRValue (right, FALSE);
3508 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3511 return geniCodeAddressOf (left);
3513 case '|': /* bitwise or & xor */
3515 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3516 geniCodeRValue (right, FALSE),
3521 return geniCodeDivision (geniCodeRValue (left, FALSE),
3522 geniCodeRValue (right, FALSE));
3525 return geniCodeModulus (geniCodeRValue (left, FALSE),
3526 geniCodeRValue (right, FALSE));
3529 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3530 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3532 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3536 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3537 geniCodeRValue (right, FALSE));
3539 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3543 return geniCodeAdd (geniCodeRValue (left, FALSE),
3544 geniCodeRValue (right, FALSE),lvl);
3546 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3549 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3550 geniCodeRValue (right, FALSE));
3553 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3554 geniCodeRValue (right, FALSE));
3556 return geniCodeCast (operandType (left),
3557 geniCodeRValue (right, FALSE), FALSE);
3563 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3567 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3568 setOperandType (op, UCHARTYPE);
3579 return geniCodeLogic (geniCodeRValue (left, FALSE),
3580 geniCodeRValue (right, FALSE),
3583 return geniCodeConditional (tree,lvl);
3586 return operandFromLit (getSize (tree->right->ftype));
3590 sym_link *rtype = operandType (right);
3591 sym_link *ltype = operandType (left);
3592 if (IS_PTR (rtype) && IS_ITEMP (right)
3593 && right->isaddr && compareType (rtype->next, ltype) == 1)
3594 right = geniCodeRValue (right, TRUE);
3596 right = geniCodeRValue (right, FALSE);
3598 geniCodeAssign (left, right, 0);
3603 geniCodeAssign (left,
3604 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3606 geniCodeRValue (right, FALSE),FALSE), 0);
3610 geniCodeAssign (left,
3611 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3613 geniCodeRValue (right, FALSE)), 0);
3616 geniCodeAssign (left,
3617 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3619 geniCodeRValue (right, FALSE)), 0);
3622 sym_link *rtype = operandType (right);
3623 sym_link *ltype = operandType (left);
3624 if (IS_PTR (rtype) && IS_ITEMP (right)
3625 && right->isaddr && compareType (rtype->next, ltype) == 1)
3626 right = geniCodeRValue (right, TRUE);
3628 right = geniCodeRValue (right, FALSE);
3631 return geniCodeAssign (left,
3632 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3638 sym_link *rtype = operandType (right);
3639 sym_link *ltype = operandType (left);
3640 if (IS_PTR (rtype) && IS_ITEMP (right)
3641 && right->isaddr && compareType (rtype->next, ltype) == 1)
3643 right = geniCodeRValue (right, TRUE);
3647 right = geniCodeRValue (right, FALSE);
3650 geniCodeAssign (left,
3651 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3657 geniCodeAssign (left,
3658 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3660 geniCodeRValue (right, FALSE)), 0);
3663 geniCodeAssign (left,
3664 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3666 geniCodeRValue (right, FALSE)), 0);
3669 geniCodeAssign (left,
3670 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3672 geniCodeRValue (right, FALSE),
3674 operandType (left)), 0);
3677 geniCodeAssign (left,
3678 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3680 geniCodeRValue (right, FALSE),
3682 operandType (left)), 0);
3685 geniCodeAssign (left,
3686 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3688 geniCodeRValue (right, FALSE),
3690 operandType (left)), 0);
3692 return geniCodeRValue (right, FALSE);
3695 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3698 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3699 return ast2iCode (tree->right,lvl+1);
3702 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3703 return ast2iCode (tree->right,lvl+1);
3706 geniCodeFunctionBody (tree,lvl);
3710 geniCodeReturn (right);
3714 geniCodeIfx (tree,lvl);
3718 geniCodeSwitch (tree,lvl);
3722 geniCodeInline (tree);
3726 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3733 /*-----------------------------------------------------------------*/
3734 /* reverseICChain - gets from the list and creates a linkedlist */
3735 /*-----------------------------------------------------------------*/
3742 while ((loop = getSet (&iCodeChain)))
3754 /*-----------------------------------------------------------------*/
3755 /* iCodeFromAst - given an ast will convert it to iCode */
3756 /*-----------------------------------------------------------------*/
3758 iCodeFromAst (ast * tree)
3760 returnLabel = newiTempLabel ("_return");
3761 entryLabel = newiTempLabel ("_entry");
3763 return reverseiCChain ();
3766 static const char *opTypeToStr(OPTYPE op)
3770 case SYMBOL: return "symbol";
3771 case VALUE: return "value";
3772 case TYPE: return "type";
3774 return "undefined type";
3778 operand *validateOpType(operand *op,
3785 if (op && op->type == type)
3790 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3791 " expected %s, got %s\n",
3792 macro, args, file, line,
3793 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3795 return op; // never reached, makes compiler happy.