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);
2121 ptype = newLink (DECLARATOR);
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,"&"); */
2454 p = newLink (DECLARATOR);
2457 /* set the pointer depending on the storage class */
2458 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2459 DCL_PTR_CONST (p) = port->mem.code_ro;
2461 /* make sure we preserve the const & volatile */
2462 if (IS_CONSTANT (opetype))
2463 DCL_PTR_CONST (p) = 1;
2465 if (IS_VOLATILE (opetype))
2466 DCL_PTR_VOLATILE (p) = 1;
2468 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2472 p->next = copyLinkChain (optype);
2474 /* if already a temp */
2477 setOperandType (op, p);
2482 /* other wise make this of the type coming in */
2483 ic = newiCode (ADDRESS_OF, op, NULL);
2484 IC_RESULT (ic) = newiTempOperand (p, 1);
2485 IC_RESULT (ic)->isaddr = 0;
2487 return IC_RESULT (ic);
2489 /*-----------------------------------------------------------------*/
2490 /* setOClass - sets the output class depending on the pointer type */
2491 /*-----------------------------------------------------------------*/
2493 setOClass (sym_link * ptr, sym_link * spec)
2495 switch (DCL_TYPE (ptr))
2498 SPEC_OCLS (spec) = data;
2502 SPEC_OCLS (spec) = generic;
2506 SPEC_OCLS (spec) = xdata;
2510 SPEC_OCLS (spec) = code;
2514 SPEC_OCLS (spec) = idata;
2518 SPEC_OCLS (spec) = xstack;
2522 SPEC_OCLS (spec) = eeprom;
2531 /*-----------------------------------------------------------------*/
2532 /* geniCodeDerefPtr - dereference pointer with '*' */
2533 /*-----------------------------------------------------------------*/
2535 geniCodeDerefPtr (operand * op,int lvl)
2537 sym_link *rtype, *retype;
2538 sym_link *optype = operandType (op);
2540 /* if this is a pointer then generate the rvalue */
2541 if (IS_PTR (optype))
2543 if (IS_TRUE_SYMOP (op))
2546 op = geniCodeRValue (op, TRUE);
2549 op = geniCodeRValue (op, TRUE);
2552 /* now get rid of the pointer part */
2553 if (isLvaluereq(lvl) && IS_ITEMP (op))
2555 retype = getSpec (rtype = copyLinkChain (optype));
2559 retype = getSpec (rtype = copyLinkChain (optype->next));
2562 /* if this is a pointer then outputclass needs 2b updated */
2563 if (IS_PTR (optype))
2564 setOClass (optype, retype);
2566 op->isGptr = IS_GENPTR (optype);
2568 /* if the pointer was declared as a constant */
2569 /* then we cannot allow assignment to the derefed */
2570 if (IS_PTR_CONST (optype))
2571 SPEC_CONST (retype) = 1;
2573 op->isaddr = (IS_PTR (rtype) ||
2574 IS_STRUCT (rtype) ||
2579 if (!isLvaluereq(lvl))
2580 op = geniCodeRValue (op, TRUE);
2582 setOperandType (op, rtype);
2587 /*-----------------------------------------------------------------*/
2588 /* geniCodeUnaryMinus - does a unary minus of the operand */
2589 /*-----------------------------------------------------------------*/
2591 geniCodeUnaryMinus (operand * op)
2594 sym_link *optype = operandType (op);
2596 if (IS_LITERAL (optype))
2597 return operandFromLit (-floatFromVal (op->operand.valOperand));
2599 ic = newiCode (UNARYMINUS, op, NULL);
2600 IC_RESULT (ic) = newiTempOperand (optype, 0);
2602 return IC_RESULT (ic);
2605 /*-----------------------------------------------------------------*/
2606 /* geniCodeLeftShift - gen i code for left shift */
2607 /*-----------------------------------------------------------------*/
2609 geniCodeLeftShift (operand * left, operand * right)
2613 ic = newiCode (LEFT_OP, left, right);
2614 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2616 return IC_RESULT (ic);
2619 /*-----------------------------------------------------------------*/
2620 /* geniCodeRightShift - gen i code for right shift */
2621 /*-----------------------------------------------------------------*/
2623 geniCodeRightShift (operand * left, operand * right)
2627 ic = newiCode (RIGHT_OP, left, right);
2628 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2630 return IC_RESULT (ic);
2633 /*-----------------------------------------------------------------*/
2634 /* geniCodeLogic- logic code */
2635 /*-----------------------------------------------------------------*/
2637 geniCodeLogic (operand * left, operand * right, int op)
2641 sym_link *rtype = operandType (right);
2642 sym_link *ltype = operandType (left);
2644 /* left is integral type and right is literal then
2645 check if the literal value is within bounds */
2646 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2648 checkConstantRange(ltype,
2649 OP_VALUE(right), "compare operation", 1);
2652 ctype = usualBinaryConversions (&left, &right);
2654 ic = newiCode (op, left, right);
2655 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2657 /* if comparing float
2658 and not a '==' || '!=' || '&&' || '||' (these
2660 if (IS_FLOAT(ctype) &&
2668 return IC_RESULT (ic);
2671 /*-----------------------------------------------------------------*/
2672 /* geniCodeUnary - for a a generic unary operation */
2673 /*-----------------------------------------------------------------*/
2675 geniCodeUnary (operand * op, int oper)
2677 iCode *ic = newiCode (oper, op, NULL);
2679 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2681 return IC_RESULT (ic);
2684 /*-----------------------------------------------------------------*/
2685 /* geniCodeConditional - geniCode for '?' ':' operation */
2686 /*-----------------------------------------------------------------*/
2688 geniCodeConditional (ast * tree,int lvl)
2691 symbol *falseLabel = newiTempLabel (NULL);
2692 symbol *exitLabel = newiTempLabel (NULL);
2693 operand *cond = ast2iCode (tree->left,lvl+1);
2694 operand *true, *false, *result;
2696 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2700 true = ast2iCode (tree->right->left,lvl+1);
2702 /* move the value to a new Operand */
2703 result = newiTempOperand (tree->right->ftype, 0);
2704 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2706 /* generate an unconditional goto */
2707 geniCodeGoto (exitLabel);
2709 /* now for the right side */
2710 geniCodeLabel (falseLabel);
2712 false = ast2iCode (tree->right->right,lvl+1);
2713 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2715 /* create the exit label */
2716 geniCodeLabel (exitLabel);
2721 /*-----------------------------------------------------------------*/
2722 /* geniCodeAssign - generate code for assignment */
2723 /*-----------------------------------------------------------------*/
2725 geniCodeAssign (operand * left, operand * right, int nosupdate)
2728 sym_link *ltype = operandType (left);
2729 sym_link *rtype = operandType (right);
2731 if (!left->isaddr && !IS_ITEMP (left))
2733 werror (E_LVALUE_REQUIRED, "assignment");
2737 /* left is integral type and right is literal then
2738 check if the literal value is within bounds */
2739 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2741 checkConstantRange(ltype,
2742 OP_VALUE(right), "= operation", 0);
2745 /* if the left & right type don't exactly match */
2746 /* if pointer set then make sure the check is
2747 done with the type & not the pointer */
2748 /* then cast rights type to left */
2750 /* first check the type for pointer assignement */
2751 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2752 compareType (ltype, rtype) <= 0)
2754 if (compareType (ltype->next, rtype) < 0)
2755 right = geniCodeCast (ltype->next, right, TRUE);
2757 else if (compareType (ltype, rtype) < 0)
2758 right = geniCodeCast (ltype, right, TRUE);
2760 /* if left is a true symbol & ! volatile
2761 create an assignment to temporary for
2762 the right & then assign this temporary
2763 to the symbol this is SSA . isn't it simple
2764 and folks have published mountains of paper on it */
2765 if (IS_TRUE_SYMOP (left) &&
2766 !isOperandVolatile (left, FALSE) &&
2767 isOperandGlobal (left))
2771 if (IS_TRUE_SYMOP (right))
2772 sym = OP_SYMBOL (right);
2773 ic = newiCode ('=', NULL, right);
2774 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2775 SPIL_LOC (right) = sym;
2779 ic = newiCode ('=', NULL, right);
2780 IC_RESULT (ic) = left;
2783 /* if left isgptr flag is set then support
2784 routine will be required */
2788 ic->nosupdate = nosupdate;
2792 /*-----------------------------------------------------------------*/
2793 /* geniCodeSEParms - generate code for side effecting fcalls */
2794 /*-----------------------------------------------------------------*/
2796 geniCodeSEParms (ast * parms,int lvl)
2801 if (parms->type == EX_OP && parms->opval.op == PARAM)
2803 geniCodeSEParms (parms->left,lvl);
2804 geniCodeSEParms (parms->right,lvl);
2808 /* hack don't like this but too lazy to think of
2810 if (IS_ADDRESS_OF_OP (parms))
2811 parms->left->lvalue = 1;
2813 if (IS_CAST_OP (parms) &&
2814 IS_PTR (parms->ftype) &&
2815 IS_ADDRESS_OF_OP (parms->right))
2816 parms->right->left->lvalue = 1;
2818 parms->opval.oprnd =
2819 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2821 parms->type = EX_OPERAND;
2822 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2823 SPEC_ARGREG(parms->ftype);
2826 /*-----------------------------------------------------------------*/
2827 /* geniCodeParms - generates parameters */
2828 /*-----------------------------------------------------------------*/
2830 geniCodeParms (ast * parms, value *argVals, int *stack,
2831 sym_link * fetype, symbol * func,int lvl)
2839 if (argVals==NULL) {
2841 argVals=FUNC_ARGS(func->type);
2844 /* if this is a param node then do the left & right */
2845 if (parms->type == EX_OP && parms->opval.op == PARAM)
2847 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2848 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2852 /* get the parameter value */
2853 if (parms->type == EX_OPERAND)
2854 pval = parms->opval.oprnd;
2857 /* maybe this else should go away ?? */
2858 /* hack don't like this but too lazy to think of
2860 if (IS_ADDRESS_OF_OP (parms))
2861 parms->left->lvalue = 1;
2863 if (IS_CAST_OP (parms) &&
2864 IS_PTR (parms->ftype) &&
2865 IS_ADDRESS_OF_OP (parms->right))
2866 parms->right->left->lvalue = 1;
2868 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2871 /* if register parm then make it a send */
2872 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2873 IFFUNC_ISBUILTIN(func->type))
2875 ic = newiCode (SEND, pval, NULL);
2876 ic->argreg = SPEC_ARGREG(parms->etype);
2877 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2882 /* now decide whether to push or assign */
2883 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2887 operand *top = operandFromSymbol (argVals->sym);
2888 /* clear useDef and other bitVectors */
2889 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2890 geniCodeAssign (top, pval, 1);
2894 sym_link *p = operandType (pval);
2896 ic = newiCode (IPUSH, pval, NULL);
2898 /* update the stack adjustment */
2899 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2904 argVals=argVals->next;
2908 /*-----------------------------------------------------------------*/
2909 /* geniCodeCall - generates temp code for calling */
2910 /*-----------------------------------------------------------------*/
2912 geniCodeCall (operand * left, ast * parms,int lvl)
2916 sym_link *type, *etype;
2919 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2920 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2921 werror (E_FUNCTION_EXPECTED);
2925 /* take care of parameters with side-effecting
2926 function calls in them, this is required to take care
2927 of overlaying function parameters */
2928 geniCodeSEParms (parms,lvl);
2930 /* first the parameters */
2931 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2933 /* now call : if symbol then pcall */
2934 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2935 ic = newiCode (PCALL, left, NULL);
2937 ic = newiCode (CALL, left, NULL);
2940 type = copyLinkChain (operandType (left)->next);
2941 etype = getSpec (type);
2942 SPEC_EXTR (etype) = 0;
2943 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2947 /* stack adjustment after call */
2948 ic->parmBytes = stack;
2953 /*-----------------------------------------------------------------*/
2954 /* geniCodeReceive - generate intermediate code for "receive" */
2955 /*-----------------------------------------------------------------*/
2957 geniCodeReceive (value * args)
2959 /* for all arguments that are passed in registers */
2963 if (IS_REGPARM (args->etype))
2965 operand *opr = operandFromValue (args);
2967 symbol *sym = OP_SYMBOL (opr);
2970 /* we will use it after all optimizations
2971 and before liveRange calculation */
2972 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2975 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2976 options.stackAuto == 0 &&
2977 (!(options.model == MODEL_FLAT24)) )
2982 opl = newiTempOperand (args->type, 0);
2984 sym->reqv->key = sym->key;
2985 OP_SYMBOL (sym->reqv)->key = sym->key;
2986 OP_SYMBOL (sym->reqv)->isreqv = 1;
2987 OP_SYMBOL (sym->reqv)->islocal = 0;
2988 SPIL_LOC (sym->reqv) = sym;
2992 ic = newiCode (RECEIVE, NULL, NULL);
2993 ic->argreg = SPEC_ARGREG(args->etype);
2995 currFunc->recvSize = getSize (sym->type);
2998 IC_RESULT (ic) = opr;
3006 /*-----------------------------------------------------------------*/
3007 /* geniCodeFunctionBody - create the function body */
3008 /*-----------------------------------------------------------------*/
3010 geniCodeFunctionBody (ast * tree,int lvl)
3017 /* reset the auto generation */
3023 func = ast2iCode (tree->left,lvl+1);
3024 fetype = getSpec (operandType (func));
3026 savelineno = lineno;
3027 lineno = OP_SYMBOL (func)->lineDef;
3028 /* create an entry label */
3029 geniCodeLabel (entryLabel);
3030 lineno = savelineno;
3032 /* create a proc icode */
3033 ic = newiCode (FUNCTION, func, NULL);
3034 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3038 /* for all parameters that are passed
3039 on registers add a "receive" */
3040 geniCodeReceive (tree->values.args);
3042 /* generate code for the body */
3043 ast2iCode (tree->right,lvl+1);
3045 /* create a label for return */
3046 geniCodeLabel (returnLabel);
3048 /* now generate the end proc */
3049 ic = newiCode (ENDFUNCTION, func, NULL);
3054 /*-----------------------------------------------------------------*/
3055 /* geniCodeReturn - gen icode for 'return' statement */
3056 /*-----------------------------------------------------------------*/
3058 geniCodeReturn (operand * op)
3062 /* if the operand is present force an rvalue */
3064 op = geniCodeRValue (op, FALSE);
3066 ic = newiCode (RETURN, op, NULL);
3070 /*-----------------------------------------------------------------*/
3071 /* geniCodeIfx - generates code for extended if statement */
3072 /*-----------------------------------------------------------------*/
3074 geniCodeIfx (ast * tree,int lvl)
3077 operand *condition = ast2iCode (tree->left,lvl+1);
3080 /* if condition is null then exit */
3084 condition = geniCodeRValue (condition, FALSE);
3086 cetype = getSpec (operandType (condition));
3087 /* if the condition is a literal */
3088 if (IS_LITERAL (cetype))
3090 if (floatFromVal (condition->operand.valOperand))
3092 if (tree->trueLabel)
3093 geniCodeGoto (tree->trueLabel);
3099 if (tree->falseLabel)
3100 geniCodeGoto (tree->falseLabel);
3107 if (tree->trueLabel)
3109 ic = newiCodeCondition (condition,
3114 if (tree->falseLabel)
3115 geniCodeGoto (tree->falseLabel);
3119 ic = newiCodeCondition (condition,
3126 ast2iCode (tree->right,lvl+1);
3129 /*-----------------------------------------------------------------*/
3130 /* geniCodeJumpTable - tries to create a jump table for switch */
3131 /*-----------------------------------------------------------------*/
3133 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3135 int min = 0, max = 0, t, cnt = 0;
3142 if (!tree || !caseVals)
3145 /* the criteria for creating a jump table is */
3146 /* all integer numbers between the maximum & minimum must */
3147 /* be present , the maximum value should not exceed 255 */
3148 min = max = (int) floatFromVal (vch = caseVals);
3149 SNPRINTF (buffer, sizeof(buffer),
3151 tree->values.switchVals.swNum,
3153 addSet (&labels, newiTempLabel (buffer));
3155 /* if there is only one case value then no need */
3156 if (!(vch = vch->next))
3161 if (((t = (int) floatFromVal (vch)) - max) != 1)
3163 SNPRINTF (buffer, sizeof(buffer),
3165 tree->values.switchVals.swNum,
3167 addSet (&labels, newiTempLabel (buffer));
3173 /* if the number of case statements <= 2 then */
3174 /* it is not economical to create the jump table */
3175 /* since two compares are needed for boundary conditions */
3176 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3179 if (tree->values.switchVals.swDefault)
3181 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3185 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3189 falseLabel = newiTempLabel (buffer);
3191 /* so we can create a jumptable */
3192 /* first we rule out the boundary conditions */
3193 /* if only optimization says so */
3194 if (!optimize.noJTabBoundary)
3196 sym_link *cetype = getSpec (operandType (cond));
3197 /* no need to check the lower bound if
3198 the condition is unsigned & minimum value is zero */
3199 if (!(min == 0 && SPEC_USIGN (cetype)))
3201 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3202 ic = newiCodeCondition (boundary, falseLabel, NULL);
3206 /* now for upper bounds */
3207 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3208 ic = newiCodeCondition (boundary, falseLabel, NULL);
3212 /* if the min is not zero then we no make it zero */
3215 cond = geniCodeSubtract (cond, operandFromLit (min));
3216 setOperandType (cond, UCHARTYPE);
3219 /* now create the jumptable */
3220 ic = newiCode (JUMPTABLE, NULL, NULL);
3221 IC_JTCOND (ic) = cond;
3222 IC_JTLABELS (ic) = labels;
3227 /*-----------------------------------------------------------------*/
3228 /* geniCodeSwitch - changes a switch to a if statement */
3229 /*-----------------------------------------------------------------*/
3231 geniCodeSwitch (ast * tree,int lvl)
3234 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3235 value *caseVals = tree->values.switchVals.swVals;
3236 symbol *trueLabel, *falseLabel;
3238 /* if we can make this a jump table */
3239 if (geniCodeJumpTable (cond, caseVals, tree))
3240 goto jumpTable; /* no need for the comparison */
3242 /* for the cases defined do */
3246 operand *compare = geniCodeLogic (cond,
3247 operandFromValue (caseVals),
3250 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3251 tree->values.switchVals.swNum,
3252 (int) floatFromVal (caseVals));
3253 trueLabel = newiTempLabel (buffer);
3255 ic = newiCodeCondition (compare, trueLabel, NULL);
3257 caseVals = caseVals->next;
3262 /* if default is present then goto break else break */
3263 if (tree->values.switchVals.swDefault)
3265 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3269 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3272 falseLabel = newiTempLabel (buffer);
3273 geniCodeGoto (falseLabel);
3276 ast2iCode (tree->right,lvl+1);
3279 /*-----------------------------------------------------------------*/
3280 /* geniCodeInline - intermediate code for inline assembler */
3281 /*-----------------------------------------------------------------*/
3283 geniCodeInline (ast * tree)
3287 ic = newiCode (INLINEASM, NULL, NULL);
3288 IC_INLINE (ic) = tree->values.inlineasm;
3292 /*-----------------------------------------------------------------*/
3293 /* geniCodeArrayInit - intermediate code for array initializer */
3294 /*-----------------------------------------------------------------*/
3296 geniCodeArrayInit (ast * tree, operand *array)
3300 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3301 ic = newiCode (ARRAYINIT, array, NULL);
3302 IC_ARRAYILIST (ic) = tree->values.constlist;
3304 operand *left=newOperand(), *right=newOperand();
3305 left->type=right->type=SYMBOL;
3306 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3307 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3308 ic = newiCode (ARRAYINIT, left, right);
3313 /*-----------------------------------------------------------------*/
3314 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3315 /* particular case. Ie : assigning or dereferencing array or ptr */
3316 /*-----------------------------------------------------------------*/
3317 set * lvaluereqSet = NULL;
3318 typedef struct lvalItem
3325 /*-----------------------------------------------------------------*/
3326 /* addLvaluereq - add a flag for lvalreq for current ast level */
3327 /*-----------------------------------------------------------------*/
3328 void addLvaluereq(int lvl)
3330 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3333 addSetHead(&lvaluereqSet,lpItem);
3336 /*-----------------------------------------------------------------*/
3337 /* delLvaluereq - del a flag for lvalreq for current ast level */
3338 /*-----------------------------------------------------------------*/
3342 lpItem = getSet(&lvaluereqSet);
3343 if(lpItem) Safe_free(lpItem);
3345 /*-----------------------------------------------------------------*/
3346 /* clearLvaluereq - clear lvalreq flag */
3347 /*-----------------------------------------------------------------*/
3348 void clearLvaluereq()
3351 lpItem = peekSet(lvaluereqSet);
3352 if(lpItem) lpItem->req = 0;
3354 /*-----------------------------------------------------------------*/
3355 /* getLvaluereq - get the last lvalreq level */
3356 /*-----------------------------------------------------------------*/
3357 int getLvaluereqLvl()
3360 lpItem = peekSet(lvaluereqSet);
3361 if(lpItem) return lpItem->lvl;
3364 /*-----------------------------------------------------------------*/
3365 /* isLvaluereq - is lvalreq valid for this level ? */
3366 /*-----------------------------------------------------------------*/
3367 int isLvaluereq(int lvl)
3370 lpItem = peekSet(lvaluereqSet);
3371 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3375 /*-----------------------------------------------------------------*/
3376 /* ast2iCode - creates an icodeList from an ast */
3377 /*-----------------------------------------------------------------*/
3379 ast2iCode (ast * tree,int lvl)
3381 operand *left = NULL;
3382 operand *right = NULL;
3386 /* set the global variables for filename & line number */
3388 filename = tree->filename;
3390 lineno = tree->lineno;
3392 block = tree->block;
3394 scopeLevel = tree->level;
3396 if (tree->type == EX_VALUE)
3397 return operandFromValue (tree->opval.val);
3399 if (tree->type == EX_LINK)
3400 return operandFromLink (tree->opval.lnk);
3402 /* if we find a nullop */
3403 if (tree->type == EX_OP &&
3404 (tree->opval.op == NULLOP ||
3405 tree->opval.op == BLOCK))
3407 ast2iCode (tree->left,lvl+1);
3408 ast2iCode (tree->right,lvl+1);
3412 /* special cases for not evaluating */
3413 if (tree->opval.op != ':' &&
3414 tree->opval.op != '?' &&
3415 tree->opval.op != CALL &&
3416 tree->opval.op != IFX &&
3417 tree->opval.op != LABEL &&
3418 tree->opval.op != GOTO &&
3419 tree->opval.op != SWITCH &&
3420 tree->opval.op != FUNCTION &&
3421 tree->opval.op != INLINEASM)
3424 if (IS_ASSIGN_OP (tree->opval.op) ||
3425 IS_DEREF_OP (tree) ||
3426 (tree->opval.op == '&' && !tree->right) ||
3427 tree->opval.op == PTR_OP)
3430 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3431 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3434 left = operandFromAst (tree->left,lvl);
3436 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3437 left = geniCodeRValue (left, TRUE);
3441 left = operandFromAst (tree->left,lvl);
3443 if (tree->opval.op == INC_OP ||
3444 tree->opval.op == DEC_OP)
3447 right = operandFromAst (tree->right,lvl);
3452 right = operandFromAst (tree->right,lvl);
3456 /* now depending on the type of operand */
3457 /* this will be a biggy */
3458 switch (tree->opval.op)
3461 case '[': /* array operation */
3463 //sym_link *ltype = operandType (left);
3464 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3465 left = geniCodeRValue (left, FALSE);
3466 right = geniCodeRValue (right, TRUE);
3469 return geniCodeArray (left, right,lvl);
3471 case '.': /* structure dereference */
3472 if (IS_PTR (operandType (left)))
3473 left = geniCodeRValue (left, TRUE);
3475 left = geniCodeRValue (left, FALSE);
3477 return geniCodeStruct (left, right, tree->lvalue);
3479 case PTR_OP: /* structure pointer dereference */
3482 pType = operandType (left);
3483 left = geniCodeRValue (left, TRUE);
3485 setOClass (pType, getSpec (operandType (left)));
3488 return geniCodeStruct (left, right, tree->lvalue);
3490 case INC_OP: /* increment operator */
3492 return geniCodePostInc (left);
3494 return geniCodePreInc (right);
3496 case DEC_OP: /* decrement operator */
3498 return geniCodePostDec (left);
3500 return geniCodePreDec (right);
3502 case '&': /* bitwise and or address of operator */
3504 { /* this is a bitwise operator */
3505 left = geniCodeRValue (left, FALSE);
3506 right = geniCodeRValue (right, FALSE);
3507 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3510 return geniCodeAddressOf (left);
3512 case '|': /* bitwise or & xor */
3514 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3515 geniCodeRValue (right, FALSE),
3520 return geniCodeDivision (geniCodeRValue (left, FALSE),
3521 geniCodeRValue (right, FALSE));
3524 return geniCodeModulus (geniCodeRValue (left, FALSE),
3525 geniCodeRValue (right, FALSE));
3528 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3529 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3531 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3535 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3536 geniCodeRValue (right, FALSE));
3538 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3542 return geniCodeAdd (geniCodeRValue (left, FALSE),
3543 geniCodeRValue (right, FALSE),lvl);
3545 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3548 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3549 geniCodeRValue (right, FALSE));
3552 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3553 geniCodeRValue (right, FALSE));
3555 return geniCodeCast (operandType (left),
3556 geniCodeRValue (right, FALSE), FALSE);
3562 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3566 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3567 setOperandType (op, UCHARTYPE);
3578 return geniCodeLogic (geniCodeRValue (left, FALSE),
3579 geniCodeRValue (right, FALSE),
3582 return geniCodeConditional (tree,lvl);
3585 return operandFromLit (getSize (tree->right->ftype));
3589 sym_link *rtype = operandType (right);
3590 sym_link *ltype = operandType (left);
3591 if (IS_PTR (rtype) && IS_ITEMP (right)
3592 && right->isaddr && compareType (rtype->next, ltype) == 1)
3593 right = geniCodeRValue (right, TRUE);
3595 right = geniCodeRValue (right, FALSE);
3597 geniCodeAssign (left, right, 0);
3602 geniCodeAssign (left,
3603 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3605 geniCodeRValue (right, FALSE),FALSE), 0);
3609 geniCodeAssign (left,
3610 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3612 geniCodeRValue (right, FALSE)), 0);
3615 geniCodeAssign (left,
3616 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3618 geniCodeRValue (right, FALSE)), 0);
3621 sym_link *rtype = operandType (right);
3622 sym_link *ltype = operandType (left);
3623 if (IS_PTR (rtype) && IS_ITEMP (right)
3624 && right->isaddr && compareType (rtype->next, ltype) == 1)
3625 right = geniCodeRValue (right, TRUE);
3627 right = geniCodeRValue (right, FALSE);
3630 return geniCodeAssign (left,
3631 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3637 sym_link *rtype = operandType (right);
3638 sym_link *ltype = operandType (left);
3639 if (IS_PTR (rtype) && IS_ITEMP (right)
3640 && right->isaddr && compareType (rtype->next, ltype) == 1)
3642 right = geniCodeRValue (right, TRUE);
3646 right = geniCodeRValue (right, FALSE);
3649 geniCodeAssign (left,
3650 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3656 geniCodeAssign (left,
3657 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3659 geniCodeRValue (right, FALSE)), 0);
3662 geniCodeAssign (left,
3663 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3665 geniCodeRValue (right, FALSE)), 0);
3668 geniCodeAssign (left,
3669 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3671 geniCodeRValue (right, FALSE),
3673 operandType (left)), 0);
3676 geniCodeAssign (left,
3677 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3679 geniCodeRValue (right, FALSE),
3681 operandType (left)), 0);
3684 geniCodeAssign (left,
3685 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3687 geniCodeRValue (right, FALSE),
3689 operandType (left)), 0);
3691 return geniCodeRValue (right, FALSE);
3694 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3697 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3698 return ast2iCode (tree->right,lvl+1);
3701 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3702 return ast2iCode (tree->right,lvl+1);
3705 geniCodeFunctionBody (tree,lvl);
3709 geniCodeReturn (right);
3713 geniCodeIfx (tree,lvl);
3717 geniCodeSwitch (tree,lvl);
3721 geniCodeInline (tree);
3725 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3732 /*-----------------------------------------------------------------*/
3733 /* reverseICChain - gets from the list and creates a linkedlist */
3734 /*-----------------------------------------------------------------*/
3741 while ((loop = getSet (&iCodeChain)))
3753 /*-----------------------------------------------------------------*/
3754 /* iCodeFromAst - given an ast will convert it to iCode */
3755 /*-----------------------------------------------------------------*/
3757 iCodeFromAst (ast * tree)
3759 returnLabel = newiTempLabel ("_return");
3760 entryLabel = newiTempLabel ("_entry");
3762 return reverseiCChain ();
3765 static const char *opTypeToStr(OPTYPE op)
3769 case SYMBOL: return "symbol";
3770 case VALUE: return "value";
3771 case TYPE: return "type";
3773 return "undefined type";
3777 operand *validateOpType(operand *op,
3784 if (op && op->type == type)
3789 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3790 " expected %s, got %s\n",
3791 macro, args, file, line,
3792 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3794 return op; // never reached, makes compiler happy.