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)
842 if (IS_ITEMP (op) && !chkTemp)
845 return IS_VOLATILE(operandType(op));
848 /*-----------------------------------------------------------------*/
849 /* isOperandLiteral - returns 1 if an operand contains a literal */
850 /*-----------------------------------------------------------------*/
852 isOperandLiteral (operand * op)
859 opetype = getSpec (operandType (op));
861 if (IS_LITERAL (opetype))
867 /*-----------------------------------------------------------------*/
868 /* isOperandInFarSpace - will return true if operand is in farSpace */
869 /*-----------------------------------------------------------------*/
871 isOperandInFarSpace (operand * op)
881 if (!IS_TRUE_SYMOP (op))
884 etype = SPIL_LOC (op)->etype;
890 etype = getSpec (operandType (op));
892 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
895 /*------------------------------------------------------------------*/
896 /* isOperandInDirSpace - will return true if operand is in dirSpace */
897 /*------------------------------------------------------------------*/
899 isOperandInDirSpace (operand * op)
909 if (!IS_TRUE_SYMOP (op))
912 etype = SPIL_LOC (op)->etype;
918 etype = getSpec (operandType (op));
920 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
923 /*--------------------------------------------------------------------*/
924 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
925 /*--------------------------------------------------------------------*/
927 isOperandInCodeSpace (operand * op)
937 etype = getSpec (operandType (op));
939 if (!IS_TRUE_SYMOP (op))
942 etype = SPIL_LOC (op)->etype;
948 etype = getSpec (operandType (op));
950 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
953 /*-----------------------------------------------------------------*/
954 /* isOperandOnStack - will return true if operand is on stack */
955 /*-----------------------------------------------------------------*/
957 isOperandOnStack (operand * op)
967 etype = getSpec (operandType (op));
968 if (IN_STACK (etype) ||
969 OP_SYMBOL(op)->onStack ||
970 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
976 /*-----------------------------------------------------------------*/
977 /* operandLitValue - literal value of an operand */
978 /*-----------------------------------------------------------------*/
980 operandLitValue (operand * op)
982 assert (isOperandLiteral (op));
984 return floatFromVal (op->operand.valOperand);
987 /*-----------------------------------------------------------------*/
988 /* getBuiltInParms - returns parameters to a builtin functions */
989 /*-----------------------------------------------------------------*/
990 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
995 /* builtin functions uses only SEND for parameters */
996 while (ic->op != CALL) {
997 assert(ic->op == SEND && ic->builtinSEND);
998 ic->generated = 1; /* mark the icode as generated */
999 parms[*pcount] = IC_LEFT(ic);
1005 /* make sure this is a builtin function call */
1006 assert(IS_SYMOP(IC_LEFT(ic)));
1007 ftype = operandType(IC_LEFT(ic));
1008 assert(IFFUNC_ISBUILTIN(ftype));
1012 /*-----------------------------------------------------------------*/
1013 /* operandOperation - perforoms operations on operands */
1014 /*-----------------------------------------------------------------*/
1016 operandOperation (operand * left, operand * right,
1017 int op, sym_link * type)
1019 sym_link *let , *ret=NULL;
1020 operand *retval = (operand *) 0;
1022 assert (isOperandLiteral (left));
1023 let = getSpec(operandType(left));
1025 assert (isOperandLiteral (right));
1026 ret = getSpec(operandType(left));
1032 retval = operandFromValue (valCastLiteral (type,
1033 operandLitValue (left) +
1034 operandLitValue (right)));
1037 retval = operandFromValue (valCastLiteral (type,
1038 operandLitValue (left) -
1039 operandLitValue (right)));
1042 retval = operandFromValue (valCastLiteral (type,
1043 operandLitValue (left) *
1044 operandLitValue (right)));
1047 if ((unsigned long) operandLitValue (right) == 0)
1049 werror (E_DIVIDE_BY_ZERO);
1054 retval = operandFromValue (valCastLiteral (type,
1055 operandLitValue (left) /
1056 operandLitValue (right)));
1059 if ((unsigned long) operandLitValue (right) == 0) {
1060 werror (E_DIVIDE_BY_ZERO);
1064 retval = operandFromLit ((SPEC_USIGN(let) ?
1065 (unsigned long) operandLitValue (left) :
1066 (long) operandLitValue (left)) %
1068 (unsigned long) operandLitValue (right) :
1069 (long) operandLitValue (right)));
1073 retval = operandFromLit ((SPEC_USIGN(let) ?
1074 (unsigned long) operandLitValue (left) :
1075 (long) operandLitValue (left)) <<
1077 (unsigned long) operandLitValue (right) :
1078 (long) operandLitValue (right)));
1081 double lval = operandLitValue(left), rval = operandLitValue(right);
1083 switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
1085 case 0: // left=unsigned right=unsigned
1086 res=(unsigned long)lval >> (unsigned long)rval;
1088 case 1: // left=unsigned right=signed
1089 res=(unsigned long)lval >> (signed long)rval;
1091 case 2: // left=signed right=unsigned
1092 res=(signed long)lval >> (unsigned long)rval;
1094 case 3: // left=signed right=signed
1095 res=(signed long)lval >> (signed long)rval;
1098 retval = operandFromLit (res);
1102 retval = operandFromLit (operandLitValue (left) ==
1103 operandLitValue (right));
1106 retval = operandFromLit (operandLitValue (left) <
1107 operandLitValue (right));
1110 retval = operandFromLit (operandLitValue (left) <=
1111 operandLitValue (right));
1114 retval = operandFromLit (operandLitValue (left) !=
1115 operandLitValue (right));
1118 retval = operandFromLit (operandLitValue (left) >
1119 operandLitValue (right));
1122 retval = operandFromLit (operandLitValue (left) >=
1123 operandLitValue (right));
1126 retval = operandFromLit ((long)operandLitValue(left) &
1127 (long)operandLitValue(right));
1130 retval = operandFromLit ((long)operandLitValue (left) |
1131 (long)operandLitValue (right));
1134 retval = operandFromLit ((long)operandLitValue (left) ^
1135 (long)operandLitValue (right));
1138 retval = operandFromLit (operandLitValue (left) &&
1139 operandLitValue (right));
1142 retval = operandFromLit (operandLitValue (left) ||
1143 operandLitValue (right));
1147 long i = (long) operandLitValue (left);
1149 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1155 long i = (long) operandLitValue (left);
1157 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1163 retval = operandFromLit (-1 * operandLitValue (left));
1167 retval = operandFromLit (~((long) operandLitValue (left)));
1171 retval = operandFromLit (!operandLitValue (left));
1175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176 " operandOperation invalid operator ");
1184 /*-----------------------------------------------------------------*/
1185 /* isOperandEqual - compares two operand & return 1 if they r = */
1186 /*-----------------------------------------------------------------*/
1188 isOperandEqual (operand * left, operand * right)
1190 /* if the pointers are equal then they are equal */
1194 /* if either of them null then false */
1195 if (!left || !right)
1198 if (left->type != right->type)
1201 if (IS_SYMOP (left) && IS_SYMOP (right))
1202 return left->key == right->key;
1204 /* if types are the same */
1208 return isSymbolEqual (left->operand.symOperand,
1209 right->operand.symOperand);
1211 return (floatFromVal (left->operand.valOperand) ==
1212 floatFromVal (right->operand.valOperand));
1214 if (compareType (left->operand.typeOperand,
1215 right->operand.typeOperand) == 1)
1222 /*-------------------------------------------------------------------*/
1223 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1224 /*-------------------------------------------------------------------*/
1226 isiCodeEqual (iCode * left, iCode * right)
1228 /* if the same pointer */
1232 /* if either of them null */
1233 if (!left || !right)
1236 /* if operand are the same */
1237 if (left->op == right->op)
1240 /* compare all the elements depending on type */
1241 if (left->op != IFX)
1243 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1245 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1251 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1253 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1255 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1264 /*-----------------------------------------------------------------*/
1265 /* newiTempFromOp - create a temp Operand with same attributes */
1266 /*-----------------------------------------------------------------*/
1268 newiTempFromOp (operand * op)
1278 nop = newiTempOperand (operandType (op), TRUE);
1279 nop->isaddr = op->isaddr;
1280 nop->isvolatile = op->isvolatile;
1281 nop->isGlobal = op->isGlobal;
1282 nop->isLiteral = op->isLiteral;
1283 nop->usesDefs = op->usesDefs;
1284 nop->isParm = op->isParm;
1288 /*-----------------------------------------------------------------*/
1289 /* operand from operand - creates an operand holder for the type */
1290 /*-----------------------------------------------------------------*/
1292 operandFromOperand (operand * op)
1298 nop = newOperand ();
1299 nop->type = op->type;
1300 nop->isaddr = op->isaddr;
1302 nop->isvolatile = op->isvolatile;
1303 nop->isGlobal = op->isGlobal;
1304 nop->isLiteral = op->isLiteral;
1305 nop->usesDefs = op->usesDefs;
1306 nop->isParm = op->isParm;
1311 nop->operand.symOperand = op->operand.symOperand;
1314 nop->operand.valOperand = op->operand.valOperand;
1317 nop->operand.typeOperand = op->operand.typeOperand;
1324 /*-----------------------------------------------------------------*/
1325 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1326 /*-----------------------------------------------------------------*/
1328 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1330 operand *nop = operandFromOperand (op);
1332 if (nop->type == SYMBOL)
1334 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1335 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1341 /*-----------------------------------------------------------------*/
1342 /* operandFromSymbol - creates an operand from a symbol */
1343 /*-----------------------------------------------------------------*/
1345 operandFromSymbol (symbol * sym)
1350 /* if the symbol's type is a literal */
1351 /* then it is an enumerator type */
1352 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1353 return operandFromValue (valFromType (sym->etype));
1356 sym->key = ++operandKey;
1358 /* if this an implicit variable, means struct/union */
1359 /* member so just return it */
1360 if (sym->implicit || IS_FUNC (sym->type))
1364 op->operand.symOperand = sym;
1366 op->isvolatile = isOperandVolatile (op, TRUE);
1367 op->isGlobal = isOperandGlobal (op);
1371 /* under the following conditions create a
1372 register equivalent for a local symbol */
1373 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1374 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1375 (!(options.model == MODEL_FLAT24)) ) &&
1376 options.stackAuto == 0)
1379 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1380 !IS_FUNC (sym->type) && /* not a function */
1381 !sym->_isparm && /* not a parameter */
1382 sym->level && /* is a local variable */
1383 !sym->addrtaken && /* whose address has not been taken */
1384 !sym->reqv && /* does not already have a reg equivalence */
1385 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1386 !IS_STATIC (sym->etype) && /* and not declared static */
1387 !sym->islbl && /* not a label */
1388 ok && /* farspace check */
1389 !IS_BITVAR (sym->etype) /* not a bit variable */
1393 /* we will use it after all optimizations
1394 and before liveRange calculation */
1395 sym->reqv = newiTempOperand (sym->type, 0);
1396 sym->reqv->key = sym->key;
1397 OP_SYMBOL (sym->reqv)->key = sym->key;
1398 OP_SYMBOL (sym->reqv)->isreqv = 1;
1399 OP_SYMBOL (sym->reqv)->islocal = 1;
1400 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1401 SPIL_LOC (sym->reqv) = sym;
1404 if (!IS_AGGREGATE (sym->type))
1408 op->operand.symOperand = sym;
1411 op->isvolatile = isOperandVolatile (op, TRUE);
1412 op->isGlobal = isOperandGlobal (op);
1413 op->isPtr = IS_PTR (operandType (op));
1414 op->isParm = sym->_isparm;
1419 /* itemp = &[_symbol] */
1421 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1422 IC_LEFT (ic)->type = SYMBOL;
1423 IC_LEFT (ic)->operand.symOperand = sym;
1424 IC_LEFT (ic)->key = sym->key;
1425 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1426 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1427 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1430 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1431 if (IS_ARRAY (sym->type))
1433 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1434 IC_RESULT (ic)->isaddr = 0;
1437 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1441 return IC_RESULT (ic);
1444 /*-----------------------------------------------------------------*/
1445 /* operandFromValue - creates an operand from value */
1446 /*-----------------------------------------------------------------*/
1448 operandFromValue (value * val)
1452 /* if this is a symbol then do the symbol thing */
1454 return operandFromSymbol (val->sym);
1456 /* this is not a symbol */
1459 op->operand.valOperand = val;
1460 op->isLiteral = isOperandLiteral (op);
1464 /*-----------------------------------------------------------------*/
1465 /* operandFromLink - operand from typeChain */
1466 /*-----------------------------------------------------------------*/
1468 operandFromLink (sym_link * type)
1472 /* operand from sym_link */
1478 op->operand.typeOperand = copyLinkChain (type);
1482 /*-----------------------------------------------------------------*/
1483 /* operandFromLit - makes an operand from a literal value */
1484 /*-----------------------------------------------------------------*/
1486 operandFromLit (double i)
1488 return operandFromValue (valueFromLit (i));
1491 /*-----------------------------------------------------------------*/
1492 /* operandFromAst - creates an operand from an ast */
1493 /*-----------------------------------------------------------------*/
1495 operandFromAst (ast * tree,int lvl)
1501 /* depending on type do */
1505 return ast2iCode (tree,lvl+1);
1509 return operandFromValue (tree->opval.val);
1513 return operandFromLink (tree->opval.lnk);
1517 /* Just to keep the comiler happy */
1518 return (operand *) 0;
1521 /*-----------------------------------------------------------------*/
1522 /* setOperandType - sets the operand's type to the given type */
1523 /*-----------------------------------------------------------------*/
1525 setOperandType (operand * op, sym_link * type)
1527 /* depending on the type of operand */
1532 op->operand.valOperand->etype =
1533 getSpec (op->operand.valOperand->type =
1534 copyLinkChain (type));
1538 if (op->operand.symOperand->isitmp)
1539 op->operand.symOperand->etype =
1540 getSpec (op->operand.symOperand->type =
1541 copyLinkChain (type));
1543 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1544 "attempt to modify type of source");
1548 op->operand.typeOperand = copyLinkChain (type);
1553 /*-----------------------------------------------------------------*/
1554 /* Get size in byte of ptr need to access an array */
1555 /*-----------------------------------------------------------------*/
1557 getArraySizePtr (operand * op)
1559 sym_link *ltype = operandType(op);
1563 int size = getSize(ltype);
1564 return(IS_GENPTR(ltype)?(size-1):size);
1569 sym_link *letype = getSpec(ltype);
1570 switch (PTR_TYPE (SPEC_OCLS (letype)))
1582 return (GPTRSIZE-1);
1591 /*-----------------------------------------------------------------*/
1592 /* perform "usual unary conversions" */
1593 /*-----------------------------------------------------------------*/
1595 usualUnaryConversions (operand * op)
1597 if (IS_INTEGRAL (operandType (op)))
1599 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1602 return geniCodeCast (INTTYPE, op, TRUE);
1608 /*-----------------------------------------------------------------*/
1609 /* perform "usual binary conversions" */
1610 /*-----------------------------------------------------------------*/
1612 usualBinaryConversions (operand ** op1, operand ** op2)
1615 sym_link *rtype = operandType (*op2);
1616 sym_link *ltype = operandType (*op1);
1618 ctype = computeType (ltype, rtype);
1620 *op1 = geniCodeCast (ctype, *op1, TRUE);
1621 *op2 = geniCodeCast (ctype, *op2, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* geniCodeValueAtAddress - generate intermeditate code for value */
1629 /*-----------------------------------------------------------------*/
1631 geniCodeRValue (operand * op, bool force)
1634 sym_link *type = operandType (op);
1635 sym_link *etype = getSpec (type);
1637 /* if this is an array & already */
1638 /* an address then return this */
1639 if (IS_AGGREGATE (type) ||
1640 (IS_PTR (type) && !force && !op->isaddr))
1641 return operandFromOperand (op);
1643 /* if this is not an address then must be */
1644 /* rvalue already so return this one */
1648 /* if this is not a temp symbol then */
1649 if (!IS_ITEMP (op) &&
1651 !IN_FARSPACE (SPEC_OCLS (etype)))
1653 op = operandFromOperand (op);
1658 if (IS_SPEC (type) &&
1659 IS_TRUE_SYMOP (op) &&
1660 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1661 (options.model == MODEL_FLAT24) ))
1663 op = operandFromOperand (op);
1668 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1669 if (IS_PTR (type) && op->isaddr && force)
1672 type = copyLinkChain (type);
1674 IC_RESULT (ic) = newiTempOperand (type, 1);
1675 IC_RESULT (ic)->isaddr = 0;
1677 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1681 return IC_RESULT (ic);
1684 /*-----------------------------------------------------------------*/
1685 /* geniCodeCast - changes the value from one type to another */
1686 /*-----------------------------------------------------------------*/
1688 geniCodeCast (sym_link * type, operand * op, bool implicit)
1692 sym_link *opetype = getSpec (optype = operandType (op));
1696 /* one of them has size zero then error */
1697 if (IS_VOID (optype))
1699 werror (E_CAST_ZERO);
1703 /* if the operand is already the desired type then do nothing */
1704 if (compareType (type, optype) == 1)
1707 /* if this is a literal then just change the type & return */
1708 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1709 return operandFromValue (valCastLiteral (type,
1710 operandLitValue (op)));
1712 /* if casting to/from pointers, do some checking */
1713 if (IS_PTR(type)) { // to a pointer
1714 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1715 if (IS_INTEGRAL(optype)) {
1716 // maybe this is NULL, than it's ok.
1717 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1718 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1719 // no way to set the storage
1720 if (IS_LITERAL(optype)) {
1721 werror(E_LITERAL_GENERIC);
1724 werror(E_NONPTR2_GENPTR);
1727 } else if (implicit) {
1728 werror(W_INTEGRAL2PTR_NOCAST);
1733 // shouldn't do that with float, array or structure unless to void
1734 if (!IS_VOID(getSpec(type)) &&
1735 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1736 werror(E_INCOMPAT_TYPES);
1740 } else { // from a pointer to a pointer
1741 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1742 // if not a pointer to a function
1743 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1744 if (implicit) { // if not to generic, they have to match
1745 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1746 werror(E_INCOMPAT_PTYPES);
1753 } else { // to a non pointer
1754 if (IS_PTR(optype)) { // from a pointer
1755 if (implicit) { // sneaky
1756 if (IS_INTEGRAL(type)) {
1757 werror(W_PTR2INTEGRAL_NOCAST);
1759 } else { // shouldn't do that with float, array or structure
1760 werror(E_INCOMPAT_TYPES);
1767 printFromToType (optype, type);
1770 /* if they are the same size create an assignment */
1771 if (getSize (type) == getSize (optype) &&
1772 !IS_BITFIELD (type) &&
1774 !IS_FLOAT (optype) &&
1775 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1776 (!IS_SPEC (type) && !IS_SPEC (optype))))
1779 ic = newiCode ('=', NULL, op);
1780 IC_RESULT (ic) = newiTempOperand (type, 0);
1781 SPIL_LOC (IC_RESULT (ic)) =
1782 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1783 IC_RESULT (ic)->isaddr = 0;
1787 ic = newiCode (CAST, operandFromLink (type),
1788 geniCodeRValue (op, FALSE));
1790 IC_RESULT (ic) = newiTempOperand (type, 0);
1793 /* preserve the storage class & output class */
1794 /* of the original variable */
1795 restype = getSpec (operandType (IC_RESULT (ic)));
1796 if (!IS_LITERAL(opetype))
1797 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1798 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1801 return IC_RESULT (ic);
1804 /*-----------------------------------------------------------------*/
1805 /* geniCodeLabel - will create a Label */
1806 /*-----------------------------------------------------------------*/
1808 geniCodeLabel (symbol * label)
1812 ic = newiCodeLabelGoto (LABEL, label);
1816 /*-----------------------------------------------------------------*/
1817 /* geniCodeGoto - will create a Goto */
1818 /*-----------------------------------------------------------------*/
1820 geniCodeGoto (symbol * label)
1824 ic = newiCodeLabelGoto (GOTO, label);
1828 /*-----------------------------------------------------------------*/
1829 /* geniCodeMultiply - gen intermediate code for multiplication */
1830 /*-----------------------------------------------------------------*/
1832 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1839 /* if they are both literal then we know the result */
1840 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1841 return operandFromValue (valMult (left->operand.valOperand,
1842 right->operand.valOperand));
1844 if (IS_LITERAL(retype)) {
1845 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1848 resType = usualBinaryConversions (&left, &right);
1850 rtype = operandType (right);
1851 retype = getSpec (rtype);
1852 ltype = operandType (left);
1853 letype = getSpec (ltype);
1857 SPEC_NOUN(getSpec(resType))=V_INT;
1860 /* if the right is a literal & power of 2 */
1861 /* then make it a left shift */
1862 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1863 efficient in most cases than 2 bytes result = 2 bytes << literal
1864 if port has 1 byte muldiv */
1865 if (p2 && !IS_FLOAT (letype) &&
1866 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1867 (port->support.muldiv == 1)))
1869 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1871 /* LEFT_OP need same size for left and result, */
1872 left = geniCodeCast (resType, left, TRUE);
1873 ltype = operandType (left);
1875 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1879 ic = newiCode ('*', left, right); /* normal multiplication */
1880 /* if the size left or right > 1 then support routine */
1881 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1885 IC_RESULT (ic) = newiTempOperand (resType, 1);
1888 return IC_RESULT (ic);
1891 /*-----------------------------------------------------------------*/
1892 /* geniCodeDivision - gen intermediate code for division */
1893 /*-----------------------------------------------------------------*/
1895 geniCodeDivision (operand * left, operand * right)
1900 sym_link *rtype = operandType (right);
1901 sym_link *retype = getSpec (rtype);
1902 sym_link *ltype = operandType (left);
1903 sym_link *letype = getSpec (ltype);
1905 resType = usualBinaryConversions (&left, &right);
1907 /* if the right is a literal & power of 2
1908 and left is unsigned then make it a
1910 if (IS_LITERAL (retype) &&
1911 !IS_FLOAT (letype) &&
1912 SPEC_USIGN(letype) &&
1913 (p2 = powof2 ((unsigned long)
1914 floatFromVal (right->operand.valOperand)))) {
1915 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1919 ic = newiCode ('/', left, right); /* normal division */
1920 /* if the size left or right > 1 then support routine */
1921 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1924 IC_RESULT (ic) = newiTempOperand (resType, 0);
1927 return IC_RESULT (ic);
1929 /*-----------------------------------------------------------------*/
1930 /* geniCodeModulus - gen intermediate code for modulus */
1931 /*-----------------------------------------------------------------*/
1933 geniCodeModulus (operand * left, operand * right)
1939 /* if they are both literal then we know the result */
1940 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1941 return operandFromValue (valMod (left->operand.valOperand,
1942 right->operand.valOperand));
1944 resType = usualBinaryConversions (&left, &right);
1946 /* now they are the same size */
1947 ic = newiCode ('%', left, right);
1949 /* if the size left or right > 1 then support routine */
1950 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1952 IC_RESULT (ic) = newiTempOperand (resType, 0);
1955 return IC_RESULT (ic);
1958 /*-----------------------------------------------------------------*/
1959 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1960 /*-----------------------------------------------------------------*/
1962 geniCodePtrPtrSubtract (operand * left, operand * right)
1968 /* if they are both literals then */
1969 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1971 result = operandFromValue (valMinus (left->operand.valOperand,
1972 right->operand.valOperand));
1976 ic = newiCode ('-', left, right);
1978 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1982 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1986 // should we really do this? is this ANSI?
1987 return geniCodeDivision (result,
1988 operandFromLit (getSize (ltype->next)));
1991 /*-----------------------------------------------------------------*/
1992 /* geniCodeSubtract - generates code for subtraction */
1993 /*-----------------------------------------------------------------*/
1995 geniCodeSubtract (operand * left, operand * right)
2002 /* if they both pointers then */
2003 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2004 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2005 return geniCodePtrPtrSubtract (left, right);
2007 /* if they are both literal then we know the result */
2008 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2009 && left->isLiteral && right->isLiteral)
2010 return operandFromValue (valMinus (left->operand.valOperand,
2011 right->operand.valOperand));
2013 /* if left is an array or pointer */
2014 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2016 isarray = left->isaddr;
2017 right = geniCodeMultiply (right,
2018 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2019 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2022 { /* make them the same size */
2023 resType = usualBinaryConversions (&left, &right);
2026 ic = newiCode ('-', left, right);
2028 IC_RESULT (ic) = newiTempOperand (resType, 1);
2029 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2031 /* if left or right is a float */
2032 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2036 return IC_RESULT (ic);
2039 /*-----------------------------------------------------------------*/
2040 /* geniCodeAdd - generates iCode for addition */
2041 /*-----------------------------------------------------------------*/
2043 geniCodeAdd (operand * left, operand * right, int lvl)
2052 /* if left is an array then array access */
2053 if (IS_ARRAY (ltype))
2054 return geniCodeArray (left, right,lvl);
2057 /* if the right side is LITERAL zero */
2058 /* return the left side */
2059 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2062 /* if left is literal zero return right */
2063 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2066 /* if left is a pointer then size */
2067 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2069 isarray = left->isaddr;
2070 // there is no need to multiply with 1
2071 if (getSize(ltype->next)!=1) {
2072 size = operandFromLit (getSize (ltype->next));
2073 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2075 resType = copyLinkChain (ltype);
2078 { // make them the same size
2079 resType = usualBinaryConversions (&left, &right);
2082 /* if they are both literals then we know */
2083 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2084 && left->isLiteral && right->isLiteral)
2085 return operandFromValue (valPlus (valFromType (letype),
2086 valFromType (retype)));
2088 ic = newiCode ('+', left, right);
2090 IC_RESULT (ic) = newiTempOperand (resType, 1);
2091 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2093 /* if left or right is a float then support
2095 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2100 return IC_RESULT (ic);
2104 /*-----------------------------------------------------------------*/
2105 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2106 /*-----------------------------------------------------------------*/
2108 aggrToPtr (sym_link * type, bool force)
2114 if (IS_PTR (type) && !force)
2117 etype = getSpec (type);
2118 ptype = newLink (DECLARATOR);
2123 /* if the output class is code */
2124 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2125 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2127 /* if the variable was declared a constant */
2128 /* then the pointer points to a constant */
2129 if (IS_CONSTANT (etype))
2130 DCL_PTR_CONST (ptype) = 1;
2132 /* the variable was volatile then pointer to volatile */
2133 if (IS_VOLATILE (etype))
2134 DCL_PTR_VOLATILE (ptype) = 1;
2136 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2142 /*-----------------------------------------------------------------*/
2143 /* geniCodeArray2Ptr - array to pointer */
2144 /*-----------------------------------------------------------------*/
2146 geniCodeArray2Ptr (operand * op)
2148 sym_link *optype = operandType (op);
2149 sym_link *opetype = getSpec (optype);
2152 /* set the pointer depending on the storage class */
2153 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2154 DCL_PTR_CONST (optype) = port->mem.code_ro;
2156 /* if the variable was declared a constant */
2157 /* then the pointer points to a constant */
2158 if (IS_CONSTANT (opetype))
2159 DCL_PTR_CONST (optype) = 1;
2161 /* the variable was volatile then pointer to volatile */
2162 if (IS_VOLATILE (opetype))
2163 DCL_PTR_VOLATILE (optype) = 1;
2165 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2173 /*-----------------------------------------------------------------*/
2174 /* geniCodeArray - array access */
2175 /*-----------------------------------------------------------------*/
2177 geniCodeArray (operand * left, operand * right,int lvl)
2180 sym_link *ltype = operandType (left);
2184 if (IS_PTR (ltype->next) && left->isaddr)
2186 left = geniCodeRValue (left, FALSE);
2188 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2191 right = geniCodeMultiply (right,
2192 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2194 /* we can check for limits here */
2195 if (isOperandLiteral (right) &&
2198 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2200 werror (E_ARRAY_BOUND);
2201 right = operandFromLit (0);
2204 ic = newiCode ('+', left, right);
2206 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2207 !IS_AGGREGATE (ltype->next) &&
2208 !IS_PTR (ltype->next))
2209 ? ltype : ltype->next), 0);
2211 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2213 return IC_RESULT (ic);
2216 /*-----------------------------------------------------------------*/
2217 /* geniCodeStruct - generates intermediate code for structres */
2218 /*-----------------------------------------------------------------*/
2220 geniCodeStruct (operand * left, operand * right, bool islval)
2223 sym_link *type = operandType (left);
2224 sym_link *etype = getSpec (type);
2226 symbol *element = getStructElement (SPEC_STRUCT (etype),
2227 right->operand.symOperand);
2229 wassert(IS_SYMOP(right));
2231 /* add the offset */
2232 ic = newiCode ('+', left, operandFromLit (element->offset));
2234 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2236 /* preserve the storage & output class of the struct */
2237 /* as well as the volatile attribute */
2238 retype = getSpec (operandType (IC_RESULT (ic)));
2239 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2240 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2241 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2243 if (IS_PTR (element->type))
2244 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2246 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2250 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2253 /*-----------------------------------------------------------------*/
2254 /* geniCodePostInc - generate int code for Post increment */
2255 /*-----------------------------------------------------------------*/
2257 geniCodePostInc (operand * op)
2261 sym_link *optype = operandType (op);
2263 operand *rv = (IS_ITEMP (op) ?
2264 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2266 sym_link *rvtype = operandType (rv);
2269 /* if this is not an address we have trouble */
2272 werror (E_LVALUE_REQUIRED, "++");
2276 rOp = newiTempOperand (rvtype, 0);
2277 OP_SYMBOL(rOp)->noSpilLoc = 1;
2280 OP_SYMBOL(rv)->noSpilLoc = 1;
2282 geniCodeAssign (rOp, rv, 0);
2284 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2285 if (IS_FLOAT (rvtype))
2286 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2288 ic = newiCode ('+', rv, operandFromLit (size));
2290 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2293 geniCodeAssign (op, result, 0);
2299 /*-----------------------------------------------------------------*/
2300 /* geniCodePreInc - generate code for preIncrement */
2301 /*-----------------------------------------------------------------*/
2303 geniCodePreInc (operand * op)
2306 sym_link *optype = operandType (op);
2307 operand *rop = (IS_ITEMP (op) ?
2308 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2310 sym_link *roptype = operandType (rop);
2316 werror (E_LVALUE_REQUIRED, "++");
2321 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2322 if (IS_FLOAT (roptype))
2323 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2325 ic = newiCode ('+', rop, operandFromLit (size));
2326 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2330 return geniCodeAssign (op, result, 0);
2333 /*-----------------------------------------------------------------*/
2334 /* geniCodePostDec - generates code for Post decrement */
2335 /*-----------------------------------------------------------------*/
2337 geniCodePostDec (operand * op)
2341 sym_link *optype = operandType (op);
2343 operand *rv = (IS_ITEMP (op) ?
2344 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2346 sym_link *rvtype = operandType (rv);
2349 /* if this is not an address we have trouble */
2352 werror (E_LVALUE_REQUIRED, "--");
2356 rOp = newiTempOperand (rvtype, 0);
2357 OP_SYMBOL(rOp)->noSpilLoc = 1;
2360 OP_SYMBOL(rv)->noSpilLoc = 1;
2362 geniCodeAssign (rOp, rv, 0);
2364 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2365 if (IS_FLOAT (rvtype))
2366 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2368 ic = newiCode ('-', rv, operandFromLit (size));
2370 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2373 geniCodeAssign (op, result, 0);
2379 /*-----------------------------------------------------------------*/
2380 /* geniCodePreDec - generate code for pre decrement */
2381 /*-----------------------------------------------------------------*/
2383 geniCodePreDec (operand * op)
2386 sym_link *optype = operandType (op);
2387 operand *rop = (IS_ITEMP (op) ?
2388 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2390 sym_link *roptype = operandType (rop);
2396 werror (E_LVALUE_REQUIRED, "--");
2401 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2402 if (IS_FLOAT (roptype))
2403 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2405 ic = newiCode ('-', rop, operandFromLit (size));
2406 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2410 return geniCodeAssign (op, result, 0);
2414 /*-----------------------------------------------------------------*/
2415 /* geniCodeBitwise - gen int code for bitWise operators */
2416 /*-----------------------------------------------------------------*/
2418 geniCodeBitwise (operand * left, operand * right,
2419 int oper, sym_link * resType)
2423 left = geniCodeCast (resType, left, TRUE);
2424 right = geniCodeCast (resType, right, TRUE);
2426 ic = newiCode (oper, left, right);
2427 IC_RESULT (ic) = newiTempOperand (resType, 0);
2430 return IC_RESULT (ic);
2433 /*-----------------------------------------------------------------*/
2434 /* geniCodeAddressOf - gens icode for '&' address of operator */
2435 /*-----------------------------------------------------------------*/
2437 geniCodeAddressOf (operand * op)
2441 sym_link *optype = operandType (op);
2442 sym_link *opetype = getSpec (optype);
2444 /* lvalue check already done in decorateType */
2445 /* this must be a lvalue */
2446 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2447 /* werror (E_LVALUE_REQUIRED,"&"); */
2451 p = newLink (DECLARATOR);
2454 /* set the pointer depending on the storage class */
2455 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2456 DCL_PTR_CONST (p) = port->mem.code_ro;
2458 /* make sure we preserve the const & volatile */
2459 if (IS_CONSTANT (opetype))
2460 DCL_PTR_CONST (p) = 1;
2462 if (IS_VOLATILE (opetype))
2463 DCL_PTR_VOLATILE (p) = 1;
2465 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2469 p->next = copyLinkChain (optype);
2471 /* if already a temp */
2474 setOperandType (op, p);
2479 /* other wise make this of the type coming in */
2480 ic = newiCode (ADDRESS_OF, op, NULL);
2481 IC_RESULT (ic) = newiTempOperand (p, 1);
2482 IC_RESULT (ic)->isaddr = 0;
2484 return IC_RESULT (ic);
2486 /*-----------------------------------------------------------------*/
2487 /* setOClass - sets the output class depending on the pointer type */
2488 /*-----------------------------------------------------------------*/
2490 setOClass (sym_link * ptr, sym_link * spec)
2492 switch (DCL_TYPE (ptr))
2495 SPEC_OCLS (spec) = data;
2499 SPEC_OCLS (spec) = generic;
2503 SPEC_OCLS (spec) = xdata;
2507 SPEC_OCLS (spec) = code;
2511 SPEC_OCLS (spec) = idata;
2515 SPEC_OCLS (spec) = xstack;
2519 SPEC_OCLS (spec) = eeprom;
2528 /*-----------------------------------------------------------------*/
2529 /* geniCodeDerefPtr - dereference pointer with '*' */
2530 /*-----------------------------------------------------------------*/
2532 geniCodeDerefPtr (operand * op,int lvl)
2534 sym_link *rtype, *retype;
2535 sym_link *optype = operandType (op);
2537 /* if this is a pointer then generate the rvalue */
2538 if (IS_PTR (optype))
2540 if (IS_TRUE_SYMOP (op))
2543 op = geniCodeRValue (op, TRUE);
2546 op = geniCodeRValue (op, TRUE);
2549 /* now get rid of the pointer part */
2550 if (isLvaluereq(lvl) && IS_ITEMP (op))
2552 retype = getSpec (rtype = copyLinkChain (optype));
2556 retype = getSpec (rtype = copyLinkChain (optype->next));
2559 /* if this is a pointer then outputclass needs 2b updated */
2560 if (IS_PTR (optype))
2561 setOClass (optype, retype);
2563 op->isGptr = IS_GENPTR (optype);
2565 /* if the pointer was declared as a constant */
2566 /* then we cannot allow assignment to the derefed */
2567 if (IS_PTR_CONST (optype))
2568 SPEC_CONST (retype) = 1;
2570 op->isaddr = (IS_PTR (rtype) ||
2571 IS_STRUCT (rtype) ||
2576 if (!isLvaluereq(lvl))
2577 op = geniCodeRValue (op, TRUE);
2579 setOperandType (op, rtype);
2584 /*-----------------------------------------------------------------*/
2585 /* geniCodeUnaryMinus - does a unary minus of the operand */
2586 /*-----------------------------------------------------------------*/
2588 geniCodeUnaryMinus (operand * op)
2591 sym_link *optype = operandType (op);
2593 if (IS_LITERAL (optype))
2594 return operandFromLit (-floatFromVal (op->operand.valOperand));
2596 ic = newiCode (UNARYMINUS, op, NULL);
2597 IC_RESULT (ic) = newiTempOperand (optype, 0);
2599 return IC_RESULT (ic);
2602 /*-----------------------------------------------------------------*/
2603 /* geniCodeLeftShift - gen i code for left shift */
2604 /*-----------------------------------------------------------------*/
2606 geniCodeLeftShift (operand * left, operand * right)
2610 ic = newiCode (LEFT_OP, left, right);
2611 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2613 return IC_RESULT (ic);
2616 /*-----------------------------------------------------------------*/
2617 /* geniCodeRightShift - gen i code for right shift */
2618 /*-----------------------------------------------------------------*/
2620 geniCodeRightShift (operand * left, operand * right)
2624 ic = newiCode (RIGHT_OP, left, right);
2625 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2627 return IC_RESULT (ic);
2630 /*-----------------------------------------------------------------*/
2631 /* geniCodeLogic- logic code */
2632 /*-----------------------------------------------------------------*/
2634 geniCodeLogic (operand * left, operand * right, int op)
2638 sym_link *rtype = operandType (right);
2639 sym_link *ltype = operandType (left);
2641 /* left is integral type and right is literal then
2642 check if the literal value is within bounds */
2643 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2645 checkConstantRange(ltype,
2646 OP_VALUE(right), "compare operation", 1);
2649 ctype = usualBinaryConversions (&left, &right);
2651 ic = newiCode (op, left, right);
2652 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2654 /* if comparing float
2655 and not a '==' || '!=' || '&&' || '||' (these
2657 if (IS_FLOAT(ctype) &&
2665 return IC_RESULT (ic);
2668 /*-----------------------------------------------------------------*/
2669 /* geniCodeUnary - for a a generic unary operation */
2670 /*-----------------------------------------------------------------*/
2672 geniCodeUnary (operand * op, int oper)
2674 iCode *ic = newiCode (oper, op, NULL);
2676 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2678 return IC_RESULT (ic);
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodeConditional - geniCode for '?' ':' operation */
2683 /*-----------------------------------------------------------------*/
2685 geniCodeConditional (ast * tree,int lvl)
2688 symbol *falseLabel = newiTempLabel (NULL);
2689 symbol *exitLabel = newiTempLabel (NULL);
2690 operand *cond = ast2iCode (tree->left,lvl+1);
2691 operand *true, *false, *result;
2693 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2697 true = ast2iCode (tree->right->left,lvl+1);
2699 /* move the value to a new Operand */
2700 result = newiTempOperand (tree->right->ftype, 0);
2701 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2703 /* generate an unconditional goto */
2704 geniCodeGoto (exitLabel);
2706 /* now for the right side */
2707 geniCodeLabel (falseLabel);
2709 false = ast2iCode (tree->right->right,lvl+1);
2710 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2712 /* create the exit label */
2713 geniCodeLabel (exitLabel);
2718 /*-----------------------------------------------------------------*/
2719 /* geniCodeAssign - generate code for assignment */
2720 /*-----------------------------------------------------------------*/
2722 geniCodeAssign (operand * left, operand * right, int nosupdate)
2725 sym_link *ltype = operandType (left);
2726 sym_link *rtype = operandType (right);
2728 if (!left->isaddr && !IS_ITEMP (left))
2730 werror (E_LVALUE_REQUIRED, "assignment");
2734 /* left is integral type and right is literal then
2735 check if the literal value is within bounds */
2736 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2738 checkConstantRange(ltype,
2739 OP_VALUE(right), "= operation", 0);
2742 /* if the left & right type don't exactly match */
2743 /* if pointer set then make sure the check is
2744 done with the type & not the pointer */
2745 /* then cast rights type to left */
2747 /* first check the type for pointer assignement */
2748 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2749 compareType (ltype, rtype) <= 0)
2751 if (compareType (ltype->next, rtype) < 0)
2752 right = geniCodeCast (ltype->next, right, TRUE);
2754 else if (compareType (ltype, rtype) < 0)
2755 right = geniCodeCast (ltype, right, TRUE);
2757 /* if left is a true symbol & ! volatile
2758 create an assignment to temporary for
2759 the right & then assign this temporary
2760 to the symbol this is SSA . isn't it simple
2761 and folks have published mountains of paper on it */
2762 if (IS_TRUE_SYMOP (left) &&
2763 !isOperandVolatile (left, FALSE) &&
2764 isOperandGlobal (left))
2768 if (IS_TRUE_SYMOP (right))
2769 sym = OP_SYMBOL (right);
2770 ic = newiCode ('=', NULL, right);
2771 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2772 SPIL_LOC (right) = sym;
2776 ic = newiCode ('=', NULL, right);
2777 IC_RESULT (ic) = left;
2780 /* if left isgptr flag is set then support
2781 routine will be required */
2785 ic->nosupdate = nosupdate;
2789 /*-----------------------------------------------------------------*/
2790 /* geniCodeSEParms - generate code for side effecting fcalls */
2791 /*-----------------------------------------------------------------*/
2793 geniCodeSEParms (ast * parms,int lvl)
2798 if (parms->type == EX_OP && parms->opval.op == PARAM)
2800 geniCodeSEParms (parms->left,lvl);
2801 geniCodeSEParms (parms->right,lvl);
2805 /* hack don't like this but too lazy to think of
2807 if (IS_ADDRESS_OF_OP (parms))
2808 parms->left->lvalue = 1;
2810 if (IS_CAST_OP (parms) &&
2811 IS_PTR (parms->ftype) &&
2812 IS_ADDRESS_OF_OP (parms->right))
2813 parms->right->left->lvalue = 1;
2815 parms->opval.oprnd =
2816 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2818 parms->type = EX_OPERAND;
2819 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2820 SPEC_ARGREG(parms->ftype);
2823 /*-----------------------------------------------------------------*/
2824 /* geniCodeParms - generates parameters */
2825 /*-----------------------------------------------------------------*/
2827 geniCodeParms (ast * parms, value *argVals, int *stack,
2828 sym_link * fetype, symbol * func,int lvl)
2836 if (argVals==NULL) {
2838 argVals=FUNC_ARGS(func->type);
2841 /* if this is a param node then do the left & right */
2842 if (parms->type == EX_OP && parms->opval.op == PARAM)
2844 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2845 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2849 /* get the parameter value */
2850 if (parms->type == EX_OPERAND)
2851 pval = parms->opval.oprnd;
2854 /* maybe this else should go away ?? */
2855 /* hack don't like this but too lazy to think of
2857 if (IS_ADDRESS_OF_OP (parms))
2858 parms->left->lvalue = 1;
2860 if (IS_CAST_OP (parms) &&
2861 IS_PTR (parms->ftype) &&
2862 IS_ADDRESS_OF_OP (parms->right))
2863 parms->right->left->lvalue = 1;
2865 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2868 /* if register parm then make it a send */
2869 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2870 IFFUNC_ISBUILTIN(func->type))
2872 ic = newiCode (SEND, pval, NULL);
2873 ic->argreg = SPEC_ARGREG(parms->etype);
2874 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2879 /* now decide whether to push or assign */
2880 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2884 operand *top = operandFromSymbol (argVals->sym);
2885 /* clear useDef and other bitVectors */
2886 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2887 geniCodeAssign (top, pval, 1);
2891 sym_link *p = operandType (pval);
2893 ic = newiCode (IPUSH, pval, NULL);
2895 /* update the stack adjustment */
2896 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2901 argVals=argVals->next;
2905 /*-----------------------------------------------------------------*/
2906 /* geniCodeCall - generates temp code for calling */
2907 /*-----------------------------------------------------------------*/
2909 geniCodeCall (operand * left, ast * parms,int lvl)
2913 sym_link *type, *etype;
2916 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2917 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2918 werror (E_FUNCTION_EXPECTED);
2922 /* take care of parameters with side-effecting
2923 function calls in them, this is required to take care
2924 of overlaying function parameters */
2925 geniCodeSEParms (parms,lvl);
2927 /* first the parameters */
2928 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2930 /* now call : if symbol then pcall */
2931 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2932 ic = newiCode (PCALL, left, NULL);
2934 ic = newiCode (CALL, left, NULL);
2937 type = copyLinkChain (operandType (left)->next);
2938 etype = getSpec (type);
2939 SPEC_EXTR (etype) = 0;
2940 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2944 /* stack adjustment after call */
2945 ic->parmBytes = stack;
2950 /*-----------------------------------------------------------------*/
2951 /* geniCodeReceive - generate intermediate code for "receive" */
2952 /*-----------------------------------------------------------------*/
2954 geniCodeReceive (value * args)
2956 /* for all arguments that are passed in registers */
2960 if (IS_REGPARM (args->etype))
2962 operand *opr = operandFromValue (args);
2964 symbol *sym = OP_SYMBOL (opr);
2967 /* we will use it after all optimizations
2968 and before liveRange calculation */
2969 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2972 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2973 options.stackAuto == 0 &&
2974 (!(options.model == MODEL_FLAT24)) )
2979 opl = newiTempOperand (args->type, 0);
2981 sym->reqv->key = sym->key;
2982 OP_SYMBOL (sym->reqv)->key = sym->key;
2983 OP_SYMBOL (sym->reqv)->isreqv = 1;
2984 OP_SYMBOL (sym->reqv)->islocal = 0;
2985 SPIL_LOC (sym->reqv) = sym;
2989 ic = newiCode (RECEIVE, NULL, NULL);
2990 ic->argreg = SPEC_ARGREG(args->etype);
2992 currFunc->recvSize = getSize (sym->type);
2995 IC_RESULT (ic) = opr;
3003 /*-----------------------------------------------------------------*/
3004 /* geniCodeFunctionBody - create the function body */
3005 /*-----------------------------------------------------------------*/
3007 geniCodeFunctionBody (ast * tree,int lvl)
3014 /* reset the auto generation */
3020 func = ast2iCode (tree->left,lvl+1);
3021 fetype = getSpec (operandType (func));
3023 savelineno = lineno;
3024 lineno = OP_SYMBOL (func)->lineDef;
3025 /* create an entry label */
3026 geniCodeLabel (entryLabel);
3027 lineno = savelineno;
3029 /* create a proc icode */
3030 ic = newiCode (FUNCTION, func, NULL);
3031 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3035 /* for all parameters that are passed
3036 on registers add a "receive" */
3037 geniCodeReceive (tree->values.args);
3039 /* generate code for the body */
3040 ast2iCode (tree->right,lvl+1);
3042 /* create a label for return */
3043 geniCodeLabel (returnLabel);
3045 /* now generate the end proc */
3046 ic = newiCode (ENDFUNCTION, func, NULL);
3051 /*-----------------------------------------------------------------*/
3052 /* geniCodeReturn - gen icode for 'return' statement */
3053 /*-----------------------------------------------------------------*/
3055 geniCodeReturn (operand * op)
3059 /* if the operand is present force an rvalue */
3061 op = geniCodeRValue (op, FALSE);
3063 ic = newiCode (RETURN, op, NULL);
3067 /*-----------------------------------------------------------------*/
3068 /* geniCodeIfx - generates code for extended if statement */
3069 /*-----------------------------------------------------------------*/
3071 geniCodeIfx (ast * tree,int lvl)
3074 operand *condition = ast2iCode (tree->left,lvl+1);
3077 /* if condition is null then exit */
3081 condition = geniCodeRValue (condition, FALSE);
3083 cetype = getSpec (operandType (condition));
3084 /* if the condition is a literal */
3085 if (IS_LITERAL (cetype))
3087 if (floatFromVal (condition->operand.valOperand))
3089 if (tree->trueLabel)
3090 geniCodeGoto (tree->trueLabel);
3096 if (tree->falseLabel)
3097 geniCodeGoto (tree->falseLabel);
3104 if (tree->trueLabel)
3106 ic = newiCodeCondition (condition,
3111 if (tree->falseLabel)
3112 geniCodeGoto (tree->falseLabel);
3116 ic = newiCodeCondition (condition,
3123 ast2iCode (tree->right,lvl+1);
3126 /*-----------------------------------------------------------------*/
3127 /* geniCodeJumpTable - tries to create a jump table for switch */
3128 /*-----------------------------------------------------------------*/
3130 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3132 int min = 0, max = 0, t, cnt = 0;
3139 if (!tree || !caseVals)
3142 /* the criteria for creating a jump table is */
3143 /* all integer numbers between the maximum & minimum must */
3144 /* be present , the maximum value should not exceed 255 */
3145 min = max = (int) floatFromVal (vch = caseVals);
3146 SNPRINTF (buffer, sizeof(buffer),
3148 tree->values.switchVals.swNum,
3150 addSet (&labels, newiTempLabel (buffer));
3152 /* if there is only one case value then no need */
3153 if (!(vch = vch->next))
3158 if (((t = (int) floatFromVal (vch)) - max) != 1)
3160 SNPRINTF (buffer, sizeof(buffer),
3162 tree->values.switchVals.swNum,
3164 addSet (&labels, newiTempLabel (buffer));
3170 /* if the number of case statements <= 2 then */
3171 /* it is not economical to create the jump table */
3172 /* since two compares are needed for boundary conditions */
3173 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3176 if (tree->values.switchVals.swDefault)
3178 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3182 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3186 falseLabel = newiTempLabel (buffer);
3188 /* so we can create a jumptable */
3189 /* first we rule out the boundary conditions */
3190 /* if only optimization says so */
3191 if (!optimize.noJTabBoundary)
3193 sym_link *cetype = getSpec (operandType (cond));
3194 /* no need to check the lower bound if
3195 the condition is unsigned & minimum value is zero */
3196 if (!(min == 0 && SPEC_USIGN (cetype)))
3198 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3199 ic = newiCodeCondition (boundary, falseLabel, NULL);
3203 /* now for upper bounds */
3204 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3205 ic = newiCodeCondition (boundary, falseLabel, NULL);
3209 /* if the min is not zero then we no make it zero */
3212 cond = geniCodeSubtract (cond, operandFromLit (min));
3213 setOperandType (cond, UCHARTYPE);
3216 /* now create the jumptable */
3217 ic = newiCode (JUMPTABLE, NULL, NULL);
3218 IC_JTCOND (ic) = cond;
3219 IC_JTLABELS (ic) = labels;
3224 /*-----------------------------------------------------------------*/
3225 /* geniCodeSwitch - changes a switch to a if statement */
3226 /*-----------------------------------------------------------------*/
3228 geniCodeSwitch (ast * tree,int lvl)
3231 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3232 value *caseVals = tree->values.switchVals.swVals;
3233 symbol *trueLabel, *falseLabel;
3235 /* if we can make this a jump table */
3236 if (geniCodeJumpTable (cond, caseVals, tree))
3237 goto jumpTable; /* no need for the comparison */
3239 /* for the cases defined do */
3243 operand *compare = geniCodeLogic (cond,
3244 operandFromValue (caseVals),
3247 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3248 tree->values.switchVals.swNum,
3249 (int) floatFromVal (caseVals));
3250 trueLabel = newiTempLabel (buffer);
3252 ic = newiCodeCondition (compare, trueLabel, NULL);
3254 caseVals = caseVals->next;
3259 /* if default is present then goto break else break */
3260 if (tree->values.switchVals.swDefault)
3262 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3266 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3269 falseLabel = newiTempLabel (buffer);
3270 geniCodeGoto (falseLabel);
3273 ast2iCode (tree->right,lvl+1);
3276 /*-----------------------------------------------------------------*/
3277 /* geniCodeInline - intermediate code for inline assembler */
3278 /*-----------------------------------------------------------------*/
3280 geniCodeInline (ast * tree)
3284 ic = newiCode (INLINEASM, NULL, NULL);
3285 IC_INLINE (ic) = tree->values.inlineasm;
3289 /*-----------------------------------------------------------------*/
3290 /* geniCodeArrayInit - intermediate code for array initializer */
3291 /*-----------------------------------------------------------------*/
3293 geniCodeArrayInit (ast * tree, operand *array)
3297 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3298 ic = newiCode (ARRAYINIT, array, NULL);
3299 IC_ARRAYILIST (ic) = tree->values.constlist;
3301 operand *left=newOperand(), *right=newOperand();
3302 left->type=right->type=SYMBOL;
3303 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3304 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3305 ic = newiCode (ARRAYINIT, left, right);
3310 /*-----------------------------------------------------------------*/
3311 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3312 /* particular case. Ie : assigning or dereferencing array or ptr */
3313 /*-----------------------------------------------------------------*/
3314 set * lvaluereqSet = NULL;
3315 typedef struct lvalItem
3322 /*-----------------------------------------------------------------*/
3323 /* addLvaluereq - add a flag for lvalreq for current ast level */
3324 /*-----------------------------------------------------------------*/
3325 void addLvaluereq(int lvl)
3327 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3330 addSetHead(&lvaluereqSet,lpItem);
3333 /*-----------------------------------------------------------------*/
3334 /* delLvaluereq - del a flag for lvalreq for current ast level */
3335 /*-----------------------------------------------------------------*/
3339 lpItem = getSet(&lvaluereqSet);
3340 if(lpItem) Safe_free(lpItem);
3342 /*-----------------------------------------------------------------*/
3343 /* clearLvaluereq - clear lvalreq flag */
3344 /*-----------------------------------------------------------------*/
3345 void clearLvaluereq()
3348 lpItem = peekSet(lvaluereqSet);
3349 if(lpItem) lpItem->req = 0;
3351 /*-----------------------------------------------------------------*/
3352 /* getLvaluereq - get the last lvalreq level */
3353 /*-----------------------------------------------------------------*/
3354 int getLvaluereqLvl()
3357 lpItem = peekSet(lvaluereqSet);
3358 if(lpItem) return lpItem->lvl;
3361 /*-----------------------------------------------------------------*/
3362 /* isLvaluereq - is lvalreq valid for this level ? */
3363 /*-----------------------------------------------------------------*/
3364 int isLvaluereq(int lvl)
3367 lpItem = peekSet(lvaluereqSet);
3368 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3372 /*-----------------------------------------------------------------*/
3373 /* ast2iCode - creates an icodeList from an ast */
3374 /*-----------------------------------------------------------------*/
3376 ast2iCode (ast * tree,int lvl)
3378 operand *left = NULL;
3379 operand *right = NULL;
3383 /* set the global variables for filename & line number */
3385 filename = tree->filename;
3387 lineno = tree->lineno;
3389 block = tree->block;
3391 scopeLevel = tree->level;
3393 if (tree->type == EX_VALUE)
3394 return operandFromValue (tree->opval.val);
3396 if (tree->type == EX_LINK)
3397 return operandFromLink (tree->opval.lnk);
3399 /* if we find a nullop */
3400 if (tree->type == EX_OP &&
3401 (tree->opval.op == NULLOP ||
3402 tree->opval.op == BLOCK))
3404 ast2iCode (tree->left,lvl+1);
3405 ast2iCode (tree->right,lvl+1);
3409 /* special cases for not evaluating */
3410 if (tree->opval.op != ':' &&
3411 tree->opval.op != '?' &&
3412 tree->opval.op != CALL &&
3413 tree->opval.op != IFX &&
3414 tree->opval.op != LABEL &&
3415 tree->opval.op != GOTO &&
3416 tree->opval.op != SWITCH &&
3417 tree->opval.op != FUNCTION &&
3418 tree->opval.op != INLINEASM)
3421 if (IS_ASSIGN_OP (tree->opval.op) ||
3422 IS_DEREF_OP (tree) ||
3423 (tree->opval.op == '&' && !tree->right) ||
3424 tree->opval.op == PTR_OP)
3427 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3428 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3431 left = operandFromAst (tree->left,lvl);
3433 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3434 left = geniCodeRValue (left, TRUE);
3438 left = operandFromAst (tree->left,lvl);
3440 if (tree->opval.op == INC_OP ||
3441 tree->opval.op == DEC_OP)
3444 right = operandFromAst (tree->right,lvl);
3449 right = operandFromAst (tree->right,lvl);
3453 /* now depending on the type of operand */
3454 /* this will be a biggy */
3455 switch (tree->opval.op)
3458 case '[': /* array operation */
3460 //sym_link *ltype = operandType (left);
3461 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3462 left = geniCodeRValue (left, FALSE);
3463 right = geniCodeRValue (right, TRUE);
3466 return geniCodeArray (left, right,lvl);
3468 case '.': /* structure dereference */
3469 if (IS_PTR (operandType (left)))
3470 left = geniCodeRValue (left, TRUE);
3472 left = geniCodeRValue (left, FALSE);
3474 return geniCodeStruct (left, right, tree->lvalue);
3476 case PTR_OP: /* structure pointer dereference */
3479 pType = operandType (left);
3480 left = geniCodeRValue (left, TRUE);
3482 setOClass (pType, getSpec (operandType (left)));
3485 return geniCodeStruct (left, right, tree->lvalue);
3487 case INC_OP: /* increment operator */
3489 return geniCodePostInc (left);
3491 return geniCodePreInc (right);
3493 case DEC_OP: /* decrement operator */
3495 return geniCodePostDec (left);
3497 return geniCodePreDec (right);
3499 case '&': /* bitwise and or address of operator */
3501 { /* this is a bitwise operator */
3502 left = geniCodeRValue (left, FALSE);
3503 right = geniCodeRValue (right, FALSE);
3504 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3507 return geniCodeAddressOf (left);
3509 case '|': /* bitwise or & xor */
3511 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3512 geniCodeRValue (right, FALSE),
3517 return geniCodeDivision (geniCodeRValue (left, FALSE),
3518 geniCodeRValue (right, FALSE));
3521 return geniCodeModulus (geniCodeRValue (left, FALSE),
3522 geniCodeRValue (right, FALSE));
3525 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3526 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3528 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3532 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3533 geniCodeRValue (right, FALSE));
3535 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3539 return geniCodeAdd (geniCodeRValue (left, FALSE),
3540 geniCodeRValue (right, FALSE),lvl);
3542 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3545 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3546 geniCodeRValue (right, FALSE));
3549 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3550 geniCodeRValue (right, FALSE));
3552 return geniCodeCast (operandType (left),
3553 geniCodeRValue (right, FALSE), FALSE);
3559 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3563 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3564 setOperandType (op, UCHARTYPE);
3575 return geniCodeLogic (geniCodeRValue (left, FALSE),
3576 geniCodeRValue (right, FALSE),
3579 return geniCodeConditional (tree,lvl);
3582 return operandFromLit (getSize (tree->right->ftype));
3586 sym_link *rtype = operandType (right);
3587 sym_link *ltype = operandType (left);
3588 if (IS_PTR (rtype) && IS_ITEMP (right)
3589 && right->isaddr && compareType (rtype->next, ltype) == 1)
3590 right = geniCodeRValue (right, TRUE);
3592 right = geniCodeRValue (right, FALSE);
3594 geniCodeAssign (left, right, 0);
3599 geniCodeAssign (left,
3600 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3602 geniCodeRValue (right, FALSE),FALSE), 0);
3606 geniCodeAssign (left,
3607 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3609 geniCodeRValue (right, FALSE)), 0);
3612 geniCodeAssign (left,
3613 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3615 geniCodeRValue (right, FALSE)), 0);
3618 sym_link *rtype = operandType (right);
3619 sym_link *ltype = operandType (left);
3620 if (IS_PTR (rtype) && IS_ITEMP (right)
3621 && right->isaddr && compareType (rtype->next, ltype) == 1)
3622 right = geniCodeRValue (right, TRUE);
3624 right = geniCodeRValue (right, FALSE);
3627 return geniCodeAssign (left,
3628 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3634 sym_link *rtype = operandType (right);
3635 sym_link *ltype = operandType (left);
3636 if (IS_PTR (rtype) && IS_ITEMP (right)
3637 && right->isaddr && compareType (rtype->next, ltype) == 1)
3639 right = geniCodeRValue (right, TRUE);
3643 right = geniCodeRValue (right, FALSE);
3646 geniCodeAssign (left,
3647 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3653 geniCodeAssign (left,
3654 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3656 geniCodeRValue (right, FALSE)), 0);
3659 geniCodeAssign (left,
3660 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3662 geniCodeRValue (right, FALSE)), 0);
3665 geniCodeAssign (left,
3666 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3668 geniCodeRValue (right, FALSE),
3670 operandType (left)), 0);
3673 geniCodeAssign (left,
3674 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3676 geniCodeRValue (right, FALSE),
3678 operandType (left)), 0);
3681 geniCodeAssign (left,
3682 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3684 geniCodeRValue (right, FALSE),
3686 operandType (left)), 0);
3688 return geniCodeRValue (right, FALSE);
3691 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3694 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3695 return ast2iCode (tree->right,lvl+1);
3698 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3699 return ast2iCode (tree->right,lvl+1);
3702 geniCodeFunctionBody (tree,lvl);
3706 geniCodeReturn (right);
3710 geniCodeIfx (tree,lvl);
3714 geniCodeSwitch (tree,lvl);
3718 geniCodeInline (tree);
3722 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3729 /*-----------------------------------------------------------------*/
3730 /* reverseICChain - gets from the list and creates a linkedlist */
3731 /*-----------------------------------------------------------------*/
3738 while ((loop = getSet (&iCodeChain)))
3750 /*-----------------------------------------------------------------*/
3751 /* iCodeFromAst - given an ast will convert it to iCode */
3752 /*-----------------------------------------------------------------*/
3754 iCodeFromAst (ast * tree)
3756 returnLabel = newiTempLabel ("_return");
3757 entryLabel = newiTempLabel ("_entry");
3759 return reverseiCChain ();
3762 static const char *opTypeToStr(OPTYPE op)
3766 case SYMBOL: return "symbol";
3767 case VALUE: return "value";
3768 case TYPE: return "type";
3770 return "undefined type";
3774 operand *validateOpType(operand *op,
3781 if (op && op->type == type)
3786 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3787 " expected %s, got %s\n",
3788 macro, args, file, line,
3789 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3791 return op; // never reached, makes compiler happy.