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 opetype = getSpec (optype = operandType (op));
850 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
853 if (IS_VOLATILE (opetype))
858 /*-----------------------------------------------------------------*/
859 /* isOperandLiteral - returns 1 if an operand contains a literal */
860 /*-----------------------------------------------------------------*/
862 isOperandLiteral (operand * op)
869 opetype = getSpec (operandType (op));
871 if (IS_LITERAL (opetype))
877 /*-----------------------------------------------------------------*/
878 /* isOperandInFarSpace - will return true if operand is in farSpace */
879 /*-----------------------------------------------------------------*/
881 isOperandInFarSpace (operand * op)
891 if (!IS_TRUE_SYMOP (op))
894 etype = SPIL_LOC (op)->etype;
900 etype = getSpec (operandType (op));
902 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
905 /*------------------------------------------------------------------*/
906 /* isOperandInDirSpace - will return true if operand is in dirSpace */
907 /*------------------------------------------------------------------*/
909 isOperandInDirSpace (operand * op)
919 if (!IS_TRUE_SYMOP (op))
922 etype = SPIL_LOC (op)->etype;
928 etype = getSpec (operandType (op));
930 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
933 /*--------------------------------------------------------------------*/
934 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
935 /*--------------------------------------------------------------------*/
937 isOperandInCodeSpace (operand * op)
947 etype = getSpec (operandType (op));
949 if (!IS_TRUE_SYMOP (op))
952 etype = SPIL_LOC (op)->etype;
958 etype = getSpec (operandType (op));
960 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
963 /*-----------------------------------------------------------------*/
964 /* isOperandOnStack - will return true if operand is on stack */
965 /*-----------------------------------------------------------------*/
967 isOperandOnStack (operand * op)
977 etype = getSpec (operandType (op));
978 if (IN_STACK (etype) ||
979 OP_SYMBOL(op)->onStack ||
980 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
986 /*-----------------------------------------------------------------*/
987 /* operandLitValue - literal value of an operand */
988 /*-----------------------------------------------------------------*/
990 operandLitValue (operand * op)
992 assert (isOperandLiteral (op));
994 return floatFromVal (op->operand.valOperand);
997 /*-----------------------------------------------------------------*/
998 /* getBuiltInParms - returns parameters to a builtin functions */
999 /*-----------------------------------------------------------------*/
1000 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1005 /* builtin functions uses only SEND for parameters */
1006 while (ic->op != CALL) {
1007 assert(ic->op == SEND && ic->builtinSEND);
1008 ic->generated = 1; /* mark the icode as generated */
1009 parms[*pcount] = IC_LEFT(ic);
1015 /* make sure this is a builtin function call */
1016 assert(IS_SYMOP(IC_LEFT(ic)));
1017 ftype = operandType(IC_LEFT(ic));
1018 assert(IFFUNC_ISBUILTIN(ftype));
1022 /*-----------------------------------------------------------------*/
1023 /* operandOperation - perforoms operations on operands */
1024 /*-----------------------------------------------------------------*/
1026 operandOperation (operand * left, operand * right,
1027 int op, sym_link * type)
1029 sym_link *let , *ret=NULL;
1030 operand *retval = (operand *) 0;
1032 assert (isOperandLiteral (left));
1033 let = getSpec(operandType(left));
1035 assert (isOperandLiteral (right));
1036 ret = getSpec(operandType(left));
1042 retval = operandFromValue (valCastLiteral (type,
1043 operandLitValue (left) +
1044 operandLitValue (right)));
1047 retval = operandFromValue (valCastLiteral (type,
1048 operandLitValue (left) -
1049 operandLitValue (right)));
1052 retval = operandFromValue (valCastLiteral (type,
1053 operandLitValue (left) *
1054 operandLitValue (right)));
1057 if ((unsigned long) operandLitValue (right) == 0)
1059 werror (E_DIVIDE_BY_ZERO);
1064 retval = operandFromValue (valCastLiteral (type,
1065 operandLitValue (left) /
1066 operandLitValue (right)));
1069 if ((unsigned long) operandLitValue (right) == 0) {
1070 werror (E_DIVIDE_BY_ZERO);
1074 retval = operandFromLit ((SPEC_USIGN(let) ?
1075 (unsigned long) operandLitValue (left) :
1076 (long) operandLitValue (left)) %
1078 (unsigned long) operandLitValue (right) :
1079 (long) operandLitValue (right)));
1083 retval = operandFromLit ((SPEC_USIGN(let) ?
1084 (unsigned long) operandLitValue (left) :
1085 (long) operandLitValue (left)) <<
1087 (unsigned long) operandLitValue (right) :
1088 (long) operandLitValue (right)));
1091 double lval = operandLitValue(left), rval = operandLitValue(right);
1093 switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
1095 case 0: // left=unsigned right=unsigned
1096 res=(unsigned long)lval >> (unsigned long)rval;
1098 case 1: // left=unsigned right=signed
1099 res=(unsigned long)lval >> (signed long)rval;
1101 case 2: // left=signed right=unsigned
1102 res=(signed long)lval >> (unsigned long)rval;
1104 case 3: // left=signed right=signed
1105 res=(signed long)lval >> (signed long)rval;
1108 retval = operandFromLit (res);
1112 retval = operandFromLit (operandLitValue (left) ==
1113 operandLitValue (right));
1116 retval = operandFromLit (operandLitValue (left) <
1117 operandLitValue (right));
1120 retval = operandFromLit (operandLitValue (left) <=
1121 operandLitValue (right));
1124 retval = operandFromLit (operandLitValue (left) !=
1125 operandLitValue (right));
1128 retval = operandFromLit (operandLitValue (left) >
1129 operandLitValue (right));
1132 retval = operandFromLit (operandLitValue (left) >=
1133 operandLitValue (right));
1136 retval = operandFromLit ((long)operandLitValue(left) &
1137 (long)operandLitValue(right));
1140 retval = operandFromLit ((long)operandLitValue (left) |
1141 (long)operandLitValue (right));
1144 retval = operandFromLit ((long)operandLitValue (left) ^
1145 (long)operandLitValue (right));
1148 retval = operandFromLit (operandLitValue (left) &&
1149 operandLitValue (right));
1152 retval = operandFromLit (operandLitValue (left) ||
1153 operandLitValue (right));
1157 long i = (long) operandLitValue (left);
1159 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1165 long i = (long) operandLitValue (left);
1167 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1173 retval = operandFromLit (-1 * operandLitValue (left));
1177 retval = operandFromLit (~((long) operandLitValue (left)));
1181 retval = operandFromLit (!operandLitValue (left));
1185 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1186 " operandOperation invalid operator ");
1194 /*-----------------------------------------------------------------*/
1195 /* isOperandEqual - compares two operand & return 1 if they r = */
1196 /*-----------------------------------------------------------------*/
1198 isOperandEqual (operand * left, operand * right)
1200 /* if the pointers are equal then they are equal */
1204 /* if either of them null then false */
1205 if (!left || !right)
1208 if (left->type != right->type)
1211 if (IS_SYMOP (left) && IS_SYMOP (right))
1212 return left->key == right->key;
1214 /* if types are the same */
1218 return isSymbolEqual (left->operand.symOperand,
1219 right->operand.symOperand);
1221 return (floatFromVal (left->operand.valOperand) ==
1222 floatFromVal (right->operand.valOperand));
1224 if (compareType (left->operand.typeOperand,
1225 right->operand.typeOperand) == 1)
1232 /*-------------------------------------------------------------------*/
1233 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1234 /*-------------------------------------------------------------------*/
1236 isiCodeEqual (iCode * left, iCode * right)
1238 /* if the same pointer */
1242 /* if either of them null */
1243 if (!left || !right)
1246 /* if operand are the same */
1247 if (left->op == right->op)
1250 /* compare all the elements depending on type */
1251 if (left->op != IFX)
1253 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1255 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1261 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1263 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1265 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1274 /*-----------------------------------------------------------------*/
1275 /* newiTempFromOp - create a temp Operand with same attributes */
1276 /*-----------------------------------------------------------------*/
1278 newiTempFromOp (operand * op)
1288 nop = newiTempOperand (operandType (op), TRUE);
1289 nop->isaddr = op->isaddr;
1290 nop->isvolatile = op->isvolatile;
1291 nop->isGlobal = op->isGlobal;
1292 nop->isLiteral = op->isLiteral;
1293 nop->usesDefs = op->usesDefs;
1294 nop->isParm = op->isParm;
1298 /*-----------------------------------------------------------------*/
1299 /* operand from operand - creates an operand holder for the type */
1300 /*-----------------------------------------------------------------*/
1302 operandFromOperand (operand * op)
1308 nop = newOperand ();
1309 nop->type = op->type;
1310 nop->isaddr = op->isaddr;
1312 nop->isvolatile = op->isvolatile;
1313 nop->isGlobal = op->isGlobal;
1314 nop->isLiteral = op->isLiteral;
1315 nop->usesDefs = op->usesDefs;
1316 nop->isParm = op->isParm;
1321 nop->operand.symOperand = op->operand.symOperand;
1324 nop->operand.valOperand = op->operand.valOperand;
1327 nop->operand.typeOperand = op->operand.typeOperand;
1334 /*-----------------------------------------------------------------*/
1335 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1336 /*-----------------------------------------------------------------*/
1338 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1340 operand *nop = operandFromOperand (op);
1342 if (nop->type == SYMBOL)
1344 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1345 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1351 /*-----------------------------------------------------------------*/
1352 /* operandFromSymbol - creates an operand from a symbol */
1353 /*-----------------------------------------------------------------*/
1355 operandFromSymbol (symbol * sym)
1360 /* if the symbol's type is a literal */
1361 /* then it is an enumerator type */
1362 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1363 return operandFromValue (valFromType (sym->etype));
1366 sym->key = ++operandKey;
1368 /* if this an implicit variable, means struct/union */
1369 /* member so just return it */
1370 if (sym->implicit || IS_FUNC (sym->type))
1374 op->operand.symOperand = sym;
1376 op->isvolatile = isOperandVolatile (op, TRUE);
1377 op->isGlobal = isOperandGlobal (op);
1381 /* under the following conditions create a
1382 register equivalent for a local symbol */
1383 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1384 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1385 (!(options.model == MODEL_FLAT24)) ) &&
1386 options.stackAuto == 0)
1389 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1390 !IS_FUNC (sym->type) && /* not a function */
1391 !sym->_isparm && /* not a parameter */
1392 sym->level && /* is a local variable */
1393 !sym->addrtaken && /* whose address has not been taken */
1394 !sym->reqv && /* does not already have a reg equivalence */
1395 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1396 !IS_STATIC (sym->etype) && /* and not declared static */
1397 !sym->islbl && /* not a label */
1398 ok && /* farspace check */
1399 !IS_BITVAR (sym->etype) /* not a bit variable */
1403 /* we will use it after all optimizations
1404 and before liveRange calculation */
1405 sym->reqv = newiTempOperand (sym->type, 0);
1406 sym->reqv->key = sym->key;
1407 OP_SYMBOL (sym->reqv)->key = sym->key;
1408 OP_SYMBOL (sym->reqv)->isreqv = 1;
1409 OP_SYMBOL (sym->reqv)->islocal = 1;
1410 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1411 SPIL_LOC (sym->reqv) = sym;
1414 if (!IS_AGGREGATE (sym->type))
1418 op->operand.symOperand = sym;
1421 op->isvolatile = isOperandVolatile (op, TRUE);
1422 op->isGlobal = isOperandGlobal (op);
1423 op->isPtr = IS_PTR (operandType (op));
1424 op->isParm = sym->_isparm;
1429 /* itemp = &[_symbol] */
1431 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1432 IC_LEFT (ic)->type = SYMBOL;
1433 IC_LEFT (ic)->operand.symOperand = sym;
1434 IC_LEFT (ic)->key = sym->key;
1435 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1436 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1437 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1440 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1441 if (IS_ARRAY (sym->type))
1443 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1444 IC_RESULT (ic)->isaddr = 0;
1447 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1451 return IC_RESULT (ic);
1454 /*-----------------------------------------------------------------*/
1455 /* operandFromValue - creates an operand from value */
1456 /*-----------------------------------------------------------------*/
1458 operandFromValue (value * val)
1462 /* if this is a symbol then do the symbol thing */
1464 return operandFromSymbol (val->sym);
1466 /* this is not a symbol */
1469 op->operand.valOperand = val;
1470 op->isLiteral = isOperandLiteral (op);
1474 /*-----------------------------------------------------------------*/
1475 /* operandFromLink - operand from typeChain */
1476 /*-----------------------------------------------------------------*/
1478 operandFromLink (sym_link * type)
1482 /* operand from sym_link */
1488 op->operand.typeOperand = copyLinkChain (type);
1492 /*-----------------------------------------------------------------*/
1493 /* operandFromLit - makes an operand from a literal value */
1494 /*-----------------------------------------------------------------*/
1496 operandFromLit (double i)
1498 return operandFromValue (valueFromLit (i));
1501 /*-----------------------------------------------------------------*/
1502 /* operandFromAst - creates an operand from an ast */
1503 /*-----------------------------------------------------------------*/
1505 operandFromAst (ast * tree,int lvl)
1511 /* depending on type do */
1515 return ast2iCode (tree,lvl+1);
1519 return operandFromValue (tree->opval.val);
1523 return operandFromLink (tree->opval.lnk);
1527 /* Just to keep the comiler happy */
1528 return (operand *) 0;
1531 /*-----------------------------------------------------------------*/
1532 /* setOperandType - sets the operand's type to the given type */
1533 /*-----------------------------------------------------------------*/
1535 setOperandType (operand * op, sym_link * type)
1537 /* depending on the type of operand */
1542 op->operand.valOperand->etype =
1543 getSpec (op->operand.valOperand->type =
1544 copyLinkChain (type));
1548 if (op->operand.symOperand->isitmp)
1549 op->operand.symOperand->etype =
1550 getSpec (op->operand.symOperand->type =
1551 copyLinkChain (type));
1553 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1554 "attempt to modify type of source");
1558 op->operand.typeOperand = copyLinkChain (type);
1563 /*-----------------------------------------------------------------*/
1564 /* Get size in byte of ptr need to access an array */
1565 /*-----------------------------------------------------------------*/
1567 getArraySizePtr (operand * op)
1569 sym_link *ltype = operandType(op);
1573 int size = getSize(ltype);
1574 return(IS_GENPTR(ltype)?(size-1):size);
1579 sym_link *letype = getSpec(ltype);
1580 switch (PTR_TYPE (SPEC_OCLS (letype)))
1592 return (GPTRSIZE-1);
1601 /*-----------------------------------------------------------------*/
1602 /* perform "usual unary conversions" */
1603 /*-----------------------------------------------------------------*/
1605 usualUnaryConversions (operand * op)
1607 if (IS_INTEGRAL (operandType (op)))
1609 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1612 return geniCodeCast (INTTYPE, op, TRUE);
1618 /*-----------------------------------------------------------------*/
1619 /* perform "usual binary conversions" */
1620 /*-----------------------------------------------------------------*/
1622 usualBinaryConversions (operand ** op1, operand ** op2)
1625 sym_link *rtype = operandType (*op2);
1626 sym_link *ltype = operandType (*op1);
1628 ctype = computeType (ltype, rtype);
1630 *op1 = geniCodeCast (ctype, *op1, TRUE);
1631 *op2 = geniCodeCast (ctype, *op2, TRUE);
1636 /*-----------------------------------------------------------------*/
1637 /* geniCodeValueAtAddress - generate intermeditate code for value */
1639 /*-----------------------------------------------------------------*/
1641 geniCodeRValue (operand * op, bool force)
1644 sym_link *type = operandType (op);
1645 sym_link *etype = getSpec (type);
1647 /* if this is an array & already */
1648 /* an address then return this */
1649 if (IS_AGGREGATE (type) ||
1650 (IS_PTR (type) && !force && !op->isaddr))
1651 return operandFromOperand (op);
1653 /* if this is not an address then must be */
1654 /* rvalue already so return this one */
1658 /* if this is not a temp symbol then */
1659 if (!IS_ITEMP (op) &&
1661 !IN_FARSPACE (SPEC_OCLS (etype)))
1663 op = operandFromOperand (op);
1668 if (IS_SPEC (type) &&
1669 IS_TRUE_SYMOP (op) &&
1670 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1671 (options.model == MODEL_FLAT24) ))
1673 op = operandFromOperand (op);
1678 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1679 if (IS_PTR (type) && op->isaddr && force)
1682 type = copyLinkChain (type);
1684 IC_RESULT (ic) = newiTempOperand (type, 1);
1685 IC_RESULT (ic)->isaddr = 0;
1687 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1691 return IC_RESULT (ic);
1694 /*-----------------------------------------------------------------*/
1695 /* geniCodeCast - changes the value from one type to another */
1696 /*-----------------------------------------------------------------*/
1698 geniCodeCast (sym_link * type, operand * op, bool implicit)
1702 sym_link *opetype = getSpec (optype = operandType (op));
1706 /* one of them has size zero then error */
1707 if (IS_VOID (optype))
1709 werror (E_CAST_ZERO);
1713 /* if the operand is already the desired type then do nothing */
1714 if (compareType (type, optype) == 1)
1717 /* if this is a literal then just change the type & return */
1718 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1719 return operandFromValue (valCastLiteral (type,
1720 operandLitValue (op)));
1722 /* if casting to/from pointers, do some checking */
1723 if (IS_PTR(type)) { // to a pointer
1724 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1725 if (IS_INTEGRAL(optype)) {
1726 // maybe this is NULL, than it's ok.
1727 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1728 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1729 // no way to set the storage
1730 if (IS_LITERAL(optype)) {
1731 werror(E_LITERAL_GENERIC);
1734 werror(E_NONPTR2_GENPTR);
1737 } else if (implicit) {
1738 werror(W_INTEGRAL2PTR_NOCAST);
1743 // shouldn't do that with float, array or structure unless to void
1744 if (!IS_VOID(getSpec(type)) &&
1745 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1746 werror(E_INCOMPAT_TYPES);
1750 } else { // from a pointer to a pointer
1751 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1752 // if not a pointer to a function
1753 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1754 if (implicit) { // if not to generic, they have to match
1755 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1756 werror(E_INCOMPAT_PTYPES);
1763 } else { // to a non pointer
1764 if (IS_PTR(optype)) { // from a pointer
1765 if (implicit) { // sneaky
1766 if (IS_INTEGRAL(type)) {
1767 werror(W_PTR2INTEGRAL_NOCAST);
1769 } else { // shouldn't do that with float, array or structure
1770 werror(E_INCOMPAT_TYPES);
1777 printFromToType (optype, type);
1780 /* if they are the same size create an assignment */
1781 if (getSize (type) == getSize (optype) &&
1782 !IS_BITFIELD (type) &&
1784 !IS_FLOAT (optype) &&
1785 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1786 (!IS_SPEC (type) && !IS_SPEC (optype))))
1789 ic = newiCode ('=', NULL, op);
1790 IC_RESULT (ic) = newiTempOperand (type, 0);
1791 SPIL_LOC (IC_RESULT (ic)) =
1792 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1793 IC_RESULT (ic)->isaddr = 0;
1797 ic = newiCode (CAST, operandFromLink (type),
1798 geniCodeRValue (op, FALSE));
1800 IC_RESULT (ic) = newiTempOperand (type, 0);
1803 /* preserve the storage class & output class */
1804 /* of the original variable */
1805 restype = getSpec (operandType (IC_RESULT (ic)));
1806 if (!IS_LITERAL(opetype))
1807 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1808 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1811 return IC_RESULT (ic);
1814 /*-----------------------------------------------------------------*/
1815 /* geniCodeLabel - will create a Label */
1816 /*-----------------------------------------------------------------*/
1818 geniCodeLabel (symbol * label)
1822 ic = newiCodeLabelGoto (LABEL, label);
1826 /*-----------------------------------------------------------------*/
1827 /* geniCodeGoto - will create a Goto */
1828 /*-----------------------------------------------------------------*/
1830 geniCodeGoto (symbol * label)
1834 ic = newiCodeLabelGoto (GOTO, label);
1838 /*-----------------------------------------------------------------*/
1839 /* geniCodeMultiply - gen intermediate code for multiplication */
1840 /*-----------------------------------------------------------------*/
1842 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1849 /* if they are both literal then we know the result */
1850 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1851 return operandFromValue (valMult (left->operand.valOperand,
1852 right->operand.valOperand));
1854 if (IS_LITERAL(retype)) {
1855 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1858 resType = usualBinaryConversions (&left, &right);
1860 rtype = operandType (right);
1861 retype = getSpec (rtype);
1862 ltype = operandType (left);
1863 letype = getSpec (ltype);
1867 SPEC_NOUN(getSpec(resType))=V_INT;
1870 /* if the right is a literal & power of 2 */
1871 /* then make it a left shift */
1872 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1873 efficient in most cases than 2 bytes result = 2 bytes << literal
1874 if port has 1 byte muldiv */
1875 if (p2 && !IS_FLOAT (letype) &&
1876 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1877 (port->support.muldiv == 1)))
1879 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1881 /* LEFT_OP need same size for left and result, */
1882 left = geniCodeCast (resType, left, TRUE);
1883 ltype = operandType (left);
1885 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1889 ic = newiCode ('*', left, right); /* normal multiplication */
1890 /* if the size left or right > 1 then support routine */
1891 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1895 IC_RESULT (ic) = newiTempOperand (resType, 1);
1898 return IC_RESULT (ic);
1901 /*-----------------------------------------------------------------*/
1902 /* geniCodeDivision - gen intermediate code for division */
1903 /*-----------------------------------------------------------------*/
1905 geniCodeDivision (operand * left, operand * right)
1910 sym_link *rtype = operandType (right);
1911 sym_link *retype = getSpec (rtype);
1912 sym_link *ltype = operandType (left);
1913 sym_link *letype = getSpec (ltype);
1915 resType = usualBinaryConversions (&left, &right);
1917 /* if the right is a literal & power of 2
1918 and left is unsigned then make it a
1920 if (IS_LITERAL (retype) &&
1921 !IS_FLOAT (letype) &&
1922 SPEC_USIGN(letype) &&
1923 (p2 = powof2 ((unsigned long)
1924 floatFromVal (right->operand.valOperand)))) {
1925 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1929 ic = newiCode ('/', left, right); /* normal division */
1930 /* if the size left or right > 1 then support routine */
1931 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1934 IC_RESULT (ic) = newiTempOperand (resType, 0);
1937 return IC_RESULT (ic);
1939 /*-----------------------------------------------------------------*/
1940 /* geniCodeModulus - gen intermediate code for modulus */
1941 /*-----------------------------------------------------------------*/
1943 geniCodeModulus (operand * left, operand * right)
1949 /* if they are both literal then we know the result */
1950 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1951 return operandFromValue (valMod (left->operand.valOperand,
1952 right->operand.valOperand));
1954 resType = usualBinaryConversions (&left, &right);
1956 /* now they are the same size */
1957 ic = newiCode ('%', left, right);
1959 /* if the size left or right > 1 then support routine */
1960 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1962 IC_RESULT (ic) = newiTempOperand (resType, 0);
1965 return IC_RESULT (ic);
1968 /*-----------------------------------------------------------------*/
1969 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1970 /*-----------------------------------------------------------------*/
1972 geniCodePtrPtrSubtract (operand * left, operand * right)
1978 /* if they are both literals then */
1979 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1981 result = operandFromValue (valMinus (left->operand.valOperand,
1982 right->operand.valOperand));
1986 ic = newiCode ('-', left, right);
1988 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1992 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1996 // should we really do this? is this ANSI?
1997 return geniCodeDivision (result,
1998 operandFromLit (getSize (ltype->next)));
2001 /*-----------------------------------------------------------------*/
2002 /* geniCodeSubtract - generates code for subtraction */
2003 /*-----------------------------------------------------------------*/
2005 geniCodeSubtract (operand * left, operand * right)
2012 /* if they both pointers then */
2013 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2014 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2015 return geniCodePtrPtrSubtract (left, right);
2017 /* if they are both literal then we know the result */
2018 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2019 && left->isLiteral && right->isLiteral)
2020 return operandFromValue (valMinus (left->operand.valOperand,
2021 right->operand.valOperand));
2023 /* if left is an array or pointer */
2024 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2026 isarray = left->isaddr;
2027 right = geniCodeMultiply (right,
2028 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2029 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2032 { /* make them the same size */
2033 resType = usualBinaryConversions (&left, &right);
2036 ic = newiCode ('-', left, right);
2038 IC_RESULT (ic) = newiTempOperand (resType, 1);
2039 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2041 /* if left or right is a float */
2042 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2046 return IC_RESULT (ic);
2049 /*-----------------------------------------------------------------*/
2050 /* geniCodeAdd - generates iCode for addition */
2051 /*-----------------------------------------------------------------*/
2053 geniCodeAdd (operand * left, operand * right, int lvl)
2062 /* if left is an array then array access */
2063 if (IS_ARRAY (ltype))
2064 return geniCodeArray (left, right,lvl);
2067 /* if the right side is LITERAL zero */
2068 /* return the left side */
2069 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2072 /* if left is literal zero return right */
2073 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2076 /* if left is a pointer then size */
2077 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2079 isarray = left->isaddr;
2080 // there is no need to multiply with 1
2081 if (getSize(ltype->next)!=1) {
2082 size = operandFromLit (getSize (ltype->next));
2083 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2085 resType = copyLinkChain (ltype);
2088 { // make them the same size
2089 resType = usualBinaryConversions (&left, &right);
2092 /* if they are both literals then we know */
2093 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2094 && left->isLiteral && right->isLiteral)
2095 return operandFromValue (valPlus (valFromType (letype),
2096 valFromType (retype)));
2098 ic = newiCode ('+', left, right);
2100 IC_RESULT (ic) = newiTempOperand (resType, 1);
2101 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2103 /* if left or right is a float then support
2105 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2110 return IC_RESULT (ic);
2114 /*-----------------------------------------------------------------*/
2115 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2116 /*-----------------------------------------------------------------*/
2118 aggrToPtr (sym_link * type, bool force)
2124 if (IS_PTR (type) && !force)
2127 etype = getSpec (type);
2128 ptype = newLink (DECLARATOR);
2132 /* if the output class is code */
2133 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2134 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2136 /* if the variable was declared a constant */
2137 /* then the pointer points to a constant */
2138 if (IS_CONSTANT (etype))
2139 DCL_PTR_CONST (ptype) = 1;
2141 /* the variable was volatile then pointer to volatile */
2142 if (IS_VOLATILE (etype))
2143 DCL_PTR_VOLATILE (ptype) = 1;
2148 /*-----------------------------------------------------------------*/
2149 /* geniCodeArray2Ptr - array to pointer */
2150 /*-----------------------------------------------------------------*/
2152 geniCodeArray2Ptr (operand * op)
2154 sym_link *optype = operandType (op);
2155 sym_link *opetype = getSpec (optype);
2157 /* set the pointer depending on the storage class */
2158 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2159 DCL_PTR_CONST (optype) = port->mem.code_ro;
2161 /* if the variable was declared a constant */
2162 /* then the pointer points to a constant */
2163 if (IS_CONSTANT (opetype))
2164 DCL_PTR_CONST (optype) = 1;
2166 /* the variable was volatile then pointer to volatile */
2167 if (IS_VOLATILE (opetype))
2168 DCL_PTR_VOLATILE (optype) = 1;
2175 /*-----------------------------------------------------------------*/
2176 /* geniCodeArray - array access */
2177 /*-----------------------------------------------------------------*/
2179 geniCodeArray (operand * left, operand * right,int lvl)
2182 sym_link *ltype = operandType (left);
2186 if (IS_PTR (ltype->next) && left->isaddr)
2188 left = geniCodeRValue (left, FALSE);
2190 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2193 right = geniCodeMultiply (right,
2194 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2196 /* we can check for limits here */
2197 if (isOperandLiteral (right) &&
2200 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2202 werror (E_ARRAY_BOUND);
2203 right = operandFromLit (0);
2206 ic = newiCode ('+', left, right);
2208 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2209 !IS_AGGREGATE (ltype->next) &&
2210 !IS_PTR (ltype->next))
2211 ? ltype : ltype->next), 0);
2213 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2215 return IC_RESULT (ic);
2218 /*-----------------------------------------------------------------*/
2219 /* geniCodeStruct - generates intermediate code for structres */
2220 /*-----------------------------------------------------------------*/
2222 geniCodeStruct (operand * left, operand * right, bool islval)
2225 sym_link *type = operandType (left);
2226 sym_link *etype = getSpec (type);
2228 symbol *element = getStructElement (SPEC_STRUCT (etype),
2229 right->operand.symOperand);
2231 wassert(IS_SYMOP(right));
2233 /* add the offset */
2234 ic = newiCode ('+', left, operandFromLit (element->offset));
2236 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2238 /* preserve the storage & output class of the struct */
2239 /* as well as the volatile attribute */
2240 retype = getSpec (operandType (IC_RESULT (ic)));
2241 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2242 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2243 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2245 if (IS_PTR (element->type))
2246 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2248 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2252 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2255 /*-----------------------------------------------------------------*/
2256 /* geniCodePostInc - generate int code for Post increment */
2257 /*-----------------------------------------------------------------*/
2259 geniCodePostInc (operand * op)
2263 sym_link *optype = operandType (op);
2265 operand *rv = (IS_ITEMP (op) ?
2266 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2268 sym_link *rvtype = operandType (rv);
2271 /* if this is not an address we have trouble */
2274 werror (E_LVALUE_REQUIRED, "++");
2278 rOp = newiTempOperand (rvtype, 0);
2279 OP_SYMBOL(rOp)->noSpilLoc = 1;
2282 OP_SYMBOL(rv)->noSpilLoc = 1;
2284 geniCodeAssign (rOp, rv, 0);
2286 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2287 if (IS_FLOAT (rvtype))
2288 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2290 ic = newiCode ('+', rv, operandFromLit (size));
2292 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2295 geniCodeAssign (op, result, 0);
2301 /*-----------------------------------------------------------------*/
2302 /* geniCodePreInc - generate code for preIncrement */
2303 /*-----------------------------------------------------------------*/
2305 geniCodePreInc (operand * op)
2308 sym_link *optype = operandType (op);
2309 operand *rop = (IS_ITEMP (op) ?
2310 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2312 sym_link *roptype = operandType (rop);
2318 werror (E_LVALUE_REQUIRED, "++");
2323 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2324 if (IS_FLOAT (roptype))
2325 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2327 ic = newiCode ('+', rop, operandFromLit (size));
2328 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2332 return geniCodeAssign (op, result, 0);
2335 /*-----------------------------------------------------------------*/
2336 /* geniCodePostDec - generates code for Post decrement */
2337 /*-----------------------------------------------------------------*/
2339 geniCodePostDec (operand * op)
2343 sym_link *optype = operandType (op);
2345 operand *rv = (IS_ITEMP (op) ?
2346 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2348 sym_link *rvtype = operandType (rv);
2351 /* if this is not an address we have trouble */
2354 werror (E_LVALUE_REQUIRED, "--");
2358 rOp = newiTempOperand (rvtype, 0);
2359 OP_SYMBOL(rOp)->noSpilLoc = 1;
2362 OP_SYMBOL(rv)->noSpilLoc = 1;
2364 geniCodeAssign (rOp, rv, 0);
2366 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2367 if (IS_FLOAT (rvtype))
2368 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2370 ic = newiCode ('-', rv, operandFromLit (size));
2372 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2375 geniCodeAssign (op, result, 0);
2381 /*-----------------------------------------------------------------*/
2382 /* geniCodePreDec - generate code for pre decrement */
2383 /*-----------------------------------------------------------------*/
2385 geniCodePreDec (operand * op)
2388 sym_link *optype = operandType (op);
2389 operand *rop = (IS_ITEMP (op) ?
2390 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2392 sym_link *roptype = operandType (rop);
2398 werror (E_LVALUE_REQUIRED, "--");
2403 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2404 if (IS_FLOAT (roptype))
2405 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2407 ic = newiCode ('-', rop, operandFromLit (size));
2408 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2412 return geniCodeAssign (op, result, 0);
2416 /*-----------------------------------------------------------------*/
2417 /* geniCodeBitwise - gen int code for bitWise operators */
2418 /*-----------------------------------------------------------------*/
2420 geniCodeBitwise (operand * left, operand * right,
2421 int oper, sym_link * resType)
2425 left = geniCodeCast (resType, left, TRUE);
2426 right = geniCodeCast (resType, right, TRUE);
2428 ic = newiCode (oper, left, right);
2429 IC_RESULT (ic) = newiTempOperand (resType, 0);
2432 return IC_RESULT (ic);
2435 /*-----------------------------------------------------------------*/
2436 /* geniCodeAddressOf - gens icode for '&' address of operator */
2437 /*-----------------------------------------------------------------*/
2439 geniCodeAddressOf (operand * op)
2443 sym_link *optype = operandType (op);
2444 sym_link *opetype = getSpec (optype);
2446 /* lvalue check already done in decorateType */
2447 /* this must be a lvalue */
2448 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2449 /* werror (E_LVALUE_REQUIRED,"&"); */
2453 p = newLink (DECLARATOR);
2455 /* set the pointer depending on the storage class */
2456 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2457 DCL_PTR_CONST (p) = port->mem.code_ro;
2459 /* make sure we preserve the const & volatile */
2460 if (IS_CONSTANT (opetype))
2461 DCL_PTR_CONST (p) = 1;
2463 if (IS_VOLATILE (opetype))
2464 DCL_PTR_VOLATILE (p) = 1;
2466 p->next = copyLinkChain (optype);
2468 /* if already a temp */
2471 setOperandType (op, p);
2476 /* other wise make this of the type coming in */
2477 ic = newiCode (ADDRESS_OF, op, NULL);
2478 IC_RESULT (ic) = newiTempOperand (p, 1);
2479 IC_RESULT (ic)->isaddr = 0;
2481 return IC_RESULT (ic);
2483 /*-----------------------------------------------------------------*/
2484 /* setOClass - sets the output class depending on the pointer type */
2485 /*-----------------------------------------------------------------*/
2487 setOClass (sym_link * ptr, sym_link * spec)
2489 switch (DCL_TYPE (ptr))
2492 SPEC_OCLS (spec) = data;
2496 SPEC_OCLS (spec) = generic;
2500 SPEC_OCLS (spec) = xdata;
2504 SPEC_OCLS (spec) = code;
2508 SPEC_OCLS (spec) = idata;
2512 SPEC_OCLS (spec) = xstack;
2516 SPEC_OCLS (spec) = eeprom;
2525 /*-----------------------------------------------------------------*/
2526 /* geniCodeDerefPtr - dereference pointer with '*' */
2527 /*-----------------------------------------------------------------*/
2529 geniCodeDerefPtr (operand * op,int lvl)
2531 sym_link *rtype, *retype;
2532 sym_link *optype = operandType (op);
2534 // if this is an array then array access
2535 if (IS_ARRAY (optype)) {
2536 // don't worry, this will be optimized out later
2537 return geniCodeArray (op, operandFromLit (0), lvl);
2540 // just in case someone screws up
2541 wassert (IS_PTR (optype));
2543 /* if this is a pointer then generate the rvalue */
2544 if (IS_PTR (optype))
2546 if (IS_TRUE_SYMOP (op))
2549 op = geniCodeRValue (op, TRUE);
2552 op = geniCodeRValue (op, TRUE);
2555 /* now get rid of the pointer part */
2556 if (isLvaluereq(lvl) && IS_ITEMP (op))
2558 retype = getSpec (rtype = copyLinkChain (optype));
2562 retype = getSpec (rtype = copyLinkChain (optype->next));
2565 /* if this is a pointer then outputclass needs 2b updated */
2566 if (IS_PTR (optype))
2567 setOClass (optype, retype);
2569 op->isGptr = IS_GENPTR (optype);
2571 /* if the pointer was declared as a constant */
2572 /* then we cannot allow assignment to the derefed */
2573 if (IS_PTR_CONST (optype))
2574 SPEC_CONST (retype) = 1;
2576 op->isaddr = (IS_PTR (rtype) ||
2577 IS_STRUCT (rtype) ||
2582 if (!isLvaluereq(lvl))
2583 op = geniCodeRValue (op, TRUE);
2585 setOperandType (op, rtype);
2590 /*-----------------------------------------------------------------*/
2591 /* geniCodeUnaryMinus - does a unary minus of the operand */
2592 /*-----------------------------------------------------------------*/
2594 geniCodeUnaryMinus (operand * op)
2597 sym_link *optype = operandType (op);
2599 if (IS_LITERAL (optype))
2600 return operandFromLit (-floatFromVal (op->operand.valOperand));
2602 ic = newiCode (UNARYMINUS, op, NULL);
2603 IC_RESULT (ic) = newiTempOperand (optype, 0);
2605 return IC_RESULT (ic);
2608 /*-----------------------------------------------------------------*/
2609 /* geniCodeLeftShift - gen i code for left shift */
2610 /*-----------------------------------------------------------------*/
2612 geniCodeLeftShift (operand * left, operand * right)
2616 ic = newiCode (LEFT_OP, left, right);
2617 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2619 return IC_RESULT (ic);
2622 /*-----------------------------------------------------------------*/
2623 /* geniCodeRightShift - gen i code for right shift */
2624 /*-----------------------------------------------------------------*/
2626 geniCodeRightShift (operand * left, operand * right)
2630 ic = newiCode (RIGHT_OP, left, right);
2631 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2633 return IC_RESULT (ic);
2636 /*-----------------------------------------------------------------*/
2637 /* geniCodeLogic- logic code */
2638 /*-----------------------------------------------------------------*/
2640 geniCodeLogic (operand * left, operand * right, int op)
2644 sym_link *rtype = operandType (right);
2645 sym_link *ltype = operandType (left);
2647 /* left is integral type and right is literal then
2648 check if the literal value is within bounds */
2649 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2651 checkConstantRange(ltype,
2652 OP_VALUE(right), "compare operation", 1);
2655 ctype = usualBinaryConversions (&left, &right);
2657 ic = newiCode (op, left, right);
2658 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2660 /* if comparing float
2661 and not a '==' || '!=' || '&&' || '||' (these
2663 if (IS_FLOAT(ctype) &&
2671 return IC_RESULT (ic);
2674 /*-----------------------------------------------------------------*/
2675 /* geniCodeUnary - for a a generic unary operation */
2676 /*-----------------------------------------------------------------*/
2678 geniCodeUnary (operand * op, int oper)
2680 iCode *ic = newiCode (oper, op, NULL);
2682 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2684 return IC_RESULT (ic);
2687 /*-----------------------------------------------------------------*/
2688 /* geniCodeConditional - geniCode for '?' ':' operation */
2689 /*-----------------------------------------------------------------*/
2691 geniCodeConditional (ast * tree,int lvl)
2694 symbol *falseLabel = newiTempLabel (NULL);
2695 symbol *exitLabel = newiTempLabel (NULL);
2696 operand *cond = ast2iCode (tree->left,lvl+1);
2697 operand *true, *false, *result;
2699 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2703 true = ast2iCode (tree->right->left,lvl+1);
2705 /* move the value to a new Operand */
2706 result = newiTempOperand (tree->right->ftype, 0);
2707 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2709 /* generate an unconditional goto */
2710 geniCodeGoto (exitLabel);
2712 /* now for the right side */
2713 geniCodeLabel (falseLabel);
2715 false = ast2iCode (tree->right->right,lvl+1);
2716 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2718 /* create the exit label */
2719 geniCodeLabel (exitLabel);
2724 /*-----------------------------------------------------------------*/
2725 /* geniCodeAssign - generate code for assignment */
2726 /*-----------------------------------------------------------------*/
2728 geniCodeAssign (operand * left, operand * right, int nosupdate)
2731 sym_link *ltype = operandType (left);
2732 sym_link *rtype = operandType (right);
2734 if (!left->isaddr && !IS_ITEMP (left))
2736 werror (E_LVALUE_REQUIRED, "assignment");
2740 /* left is integral type and right is literal then
2741 check if the literal value is within bounds */
2742 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2744 checkConstantRange(ltype,
2745 OP_VALUE(right), "= operation", 0);
2748 /* if the left & right type don't exactly match */
2749 /* if pointer set then make sure the check is
2750 done with the type & not the pointer */
2751 /* then cast rights type to left */
2753 /* first check the type for pointer assignement */
2754 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2755 compareType (ltype, rtype) <= 0)
2757 if (compareType (ltype->next, rtype) < 0)
2758 right = geniCodeCast (ltype->next, right, TRUE);
2760 else if (compareType (ltype, rtype) < 0)
2761 right = geniCodeCast (ltype, right, TRUE);
2763 /* if left is a true symbol & ! volatile
2764 create an assignment to temporary for
2765 the right & then assign this temporary
2766 to the symbol this is SSA . isn't it simple
2767 and folks have published mountains of paper on it */
2768 if (IS_TRUE_SYMOP (left) &&
2769 !isOperandVolatile (left, FALSE) &&
2770 isOperandGlobal (left))
2774 if (IS_TRUE_SYMOP (right))
2775 sym = OP_SYMBOL (right);
2776 ic = newiCode ('=', NULL, right);
2777 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2778 SPIL_LOC (right) = sym;
2782 ic = newiCode ('=', NULL, right);
2783 IC_RESULT (ic) = left;
2786 /* if left isgptr flag is set then support
2787 routine will be required */
2791 ic->nosupdate = nosupdate;
2795 /*-----------------------------------------------------------------*/
2796 /* geniCodeSEParms - generate code for side effecting fcalls */
2797 /*-----------------------------------------------------------------*/
2799 geniCodeSEParms (ast * parms,int lvl)
2804 if (parms->type == EX_OP && parms->opval.op == PARAM)
2806 geniCodeSEParms (parms->left,lvl);
2807 geniCodeSEParms (parms->right,lvl);
2811 /* hack don't like this but too lazy to think of
2813 if (IS_ADDRESS_OF_OP (parms))
2814 parms->left->lvalue = 1;
2816 if (IS_CAST_OP (parms) &&
2817 IS_PTR (parms->ftype) &&
2818 IS_ADDRESS_OF_OP (parms->right))
2819 parms->right->left->lvalue = 1;
2821 parms->opval.oprnd =
2822 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2824 parms->type = EX_OPERAND;
2825 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2826 SPEC_ARGREG(parms->ftype);
2829 /*-----------------------------------------------------------------*/
2830 /* geniCodeParms - generates parameters */
2831 /*-----------------------------------------------------------------*/
2833 geniCodeParms (ast * parms, value *argVals, int *stack,
2834 sym_link * fetype, symbol * func,int lvl)
2842 if (argVals==NULL) {
2844 argVals=FUNC_ARGS(func->type);
2847 /* if this is a param node then do the left & right */
2848 if (parms->type == EX_OP && parms->opval.op == PARAM)
2850 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2851 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2855 /* get the parameter value */
2856 if (parms->type == EX_OPERAND)
2857 pval = parms->opval.oprnd;
2860 /* maybe this else should go away ?? */
2861 /* hack don't like this but too lazy to think of
2863 if (IS_ADDRESS_OF_OP (parms))
2864 parms->left->lvalue = 1;
2866 if (IS_CAST_OP (parms) &&
2867 IS_PTR (parms->ftype) &&
2868 IS_ADDRESS_OF_OP (parms->right))
2869 parms->right->left->lvalue = 1;
2871 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2874 /* if register parm then make it a send */
2875 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2876 IFFUNC_ISBUILTIN(func->type))
2878 ic = newiCode (SEND, pval, NULL);
2879 ic->argreg = SPEC_ARGREG(parms->etype);
2880 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2885 /* now decide whether to push or assign */
2886 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2890 operand *top = operandFromSymbol (argVals->sym);
2891 /* clear useDef and other bitVectors */
2892 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2893 geniCodeAssign (top, pval, 1);
2897 sym_link *p = operandType (pval);
2899 ic = newiCode (IPUSH, pval, NULL);
2901 /* update the stack adjustment */
2902 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2907 argVals=argVals->next;
2911 /*-----------------------------------------------------------------*/
2912 /* geniCodeCall - generates temp code for calling */
2913 /*-----------------------------------------------------------------*/
2915 geniCodeCall (operand * left, ast * parms,int lvl)
2919 sym_link *type, *etype;
2922 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2923 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2924 werror (E_FUNCTION_EXPECTED);
2928 /* take care of parameters with side-effecting
2929 function calls in them, this is required to take care
2930 of overlaying function parameters */
2931 geniCodeSEParms (parms,lvl);
2933 /* first the parameters */
2934 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2936 /* now call : if symbol then pcall */
2937 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2938 ic = newiCode (PCALL, left, NULL);
2940 ic = newiCode (CALL, left, NULL);
2943 type = copyLinkChain (operandType (left)->next);
2944 etype = getSpec (type);
2945 SPEC_EXTR (etype) = 0;
2946 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2950 /* stack adjustment after call */
2951 ic->parmBytes = stack;
2956 /*-----------------------------------------------------------------*/
2957 /* geniCodeReceive - generate intermediate code for "receive" */
2958 /*-----------------------------------------------------------------*/
2960 geniCodeReceive (value * args)
2962 /* for all arguments that are passed in registers */
2966 if (IS_REGPARM (args->etype))
2968 operand *opr = operandFromValue (args);
2970 symbol *sym = OP_SYMBOL (opr);
2973 /* we will use it after all optimizations
2974 and before liveRange calculation */
2975 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2978 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2979 options.stackAuto == 0 &&
2980 (!(options.model == MODEL_FLAT24)) )
2985 opl = newiTempOperand (args->type, 0);
2987 sym->reqv->key = sym->key;
2988 OP_SYMBOL (sym->reqv)->key = sym->key;
2989 OP_SYMBOL (sym->reqv)->isreqv = 1;
2990 OP_SYMBOL (sym->reqv)->islocal = 0;
2991 SPIL_LOC (sym->reqv) = sym;
2995 ic = newiCode (RECEIVE, NULL, NULL);
2996 ic->argreg = SPEC_ARGREG(args->etype);
2998 currFunc->recvSize = getSize (sym->type);
3001 IC_RESULT (ic) = opr;
3009 /*-----------------------------------------------------------------*/
3010 /* geniCodeFunctionBody - create the function body */
3011 /*-----------------------------------------------------------------*/
3013 geniCodeFunctionBody (ast * tree,int lvl)
3020 /* reset the auto generation */
3026 func = ast2iCode (tree->left,lvl+1);
3027 fetype = getSpec (operandType (func));
3029 savelineno = lineno;
3030 lineno = OP_SYMBOL (func)->lineDef;
3031 /* create an entry label */
3032 geniCodeLabel (entryLabel);
3033 lineno = savelineno;
3035 /* create a proc icode */
3036 ic = newiCode (FUNCTION, func, NULL);
3037 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3041 /* for all parameters that are passed
3042 on registers add a "receive" */
3043 geniCodeReceive (tree->values.args);
3045 /* generate code for the body */
3046 ast2iCode (tree->right,lvl+1);
3048 /* create a label for return */
3049 geniCodeLabel (returnLabel);
3051 /* now generate the end proc */
3052 ic = newiCode (ENDFUNCTION, func, NULL);
3057 /*-----------------------------------------------------------------*/
3058 /* geniCodeReturn - gen icode for 'return' statement */
3059 /*-----------------------------------------------------------------*/
3061 geniCodeReturn (operand * op)
3065 /* if the operand is present force an rvalue */
3067 op = geniCodeRValue (op, FALSE);
3069 ic = newiCode (RETURN, op, NULL);
3073 /*-----------------------------------------------------------------*/
3074 /* geniCodeIfx - generates code for extended if statement */
3075 /*-----------------------------------------------------------------*/
3077 geniCodeIfx (ast * tree,int lvl)
3080 operand *condition = ast2iCode (tree->left,lvl+1);
3083 /* if condition is null then exit */
3087 condition = geniCodeRValue (condition, FALSE);
3089 cetype = getSpec (operandType (condition));
3090 /* if the condition is a literal */
3091 if (IS_LITERAL (cetype))
3093 if (floatFromVal (condition->operand.valOperand))
3095 if (tree->trueLabel)
3096 geniCodeGoto (tree->trueLabel);
3102 if (tree->falseLabel)
3103 geniCodeGoto (tree->falseLabel);
3110 if (tree->trueLabel)
3112 ic = newiCodeCondition (condition,
3117 if (tree->falseLabel)
3118 geniCodeGoto (tree->falseLabel);
3122 ic = newiCodeCondition (condition,
3129 ast2iCode (tree->right,lvl+1);
3132 /*-----------------------------------------------------------------*/
3133 /* geniCodeJumpTable - tries to create a jump table for switch */
3134 /*-----------------------------------------------------------------*/
3136 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3138 int min = 0, max = 0, t, cnt = 0;
3145 if (!tree || !caseVals)
3148 /* the criteria for creating a jump table is */
3149 /* all integer numbers between the maximum & minimum must */
3150 /* be present , the maximum value should not exceed 255 */
3151 min = max = (int) floatFromVal (vch = caseVals);
3152 SNPRINTF (buffer, sizeof(buffer),
3154 tree->values.switchVals.swNum,
3156 addSet (&labels, newiTempLabel (buffer));
3158 /* if there is only one case value then no need */
3159 if (!(vch = vch->next))
3164 if (((t = (int) floatFromVal (vch)) - max) != 1)
3166 SNPRINTF (buffer, sizeof(buffer),
3168 tree->values.switchVals.swNum,
3170 addSet (&labels, newiTempLabel (buffer));
3176 /* if the number of case statements <= 2 then */
3177 /* it is not economical to create the jump table */
3178 /* since two compares are needed for boundary conditions */
3179 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3182 if (tree->values.switchVals.swDefault)
3184 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3188 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3192 falseLabel = newiTempLabel (buffer);
3194 /* so we can create a jumptable */
3195 /* first we rule out the boundary conditions */
3196 /* if only optimization says so */
3197 if (!optimize.noJTabBoundary)
3199 sym_link *cetype = getSpec (operandType (cond));
3200 /* no need to check the lower bound if
3201 the condition is unsigned & minimum value is zero */
3202 if (!(min == 0 && SPEC_USIGN (cetype)))
3204 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3205 ic = newiCodeCondition (boundary, falseLabel, NULL);
3209 /* now for upper bounds */
3210 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3211 ic = newiCodeCondition (boundary, falseLabel, NULL);
3215 /* if the min is not zero then we no make it zero */
3218 cond = geniCodeSubtract (cond, operandFromLit (min));
3219 setOperandType (cond, UCHARTYPE);
3222 /* now create the jumptable */
3223 ic = newiCode (JUMPTABLE, NULL, NULL);
3224 IC_JTCOND (ic) = cond;
3225 IC_JTLABELS (ic) = labels;
3230 /*-----------------------------------------------------------------*/
3231 /* geniCodeSwitch - changes a switch to a if statement */
3232 /*-----------------------------------------------------------------*/
3234 geniCodeSwitch (ast * tree,int lvl)
3237 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3238 value *caseVals = tree->values.switchVals.swVals;
3239 symbol *trueLabel, *falseLabel;
3241 /* if we can make this a jump table */
3242 if (geniCodeJumpTable (cond, caseVals, tree))
3243 goto jumpTable; /* no need for the comparison */
3245 /* for the cases defined do */
3249 operand *compare = geniCodeLogic (cond,
3250 operandFromValue (caseVals),
3253 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3254 tree->values.switchVals.swNum,
3255 (int) floatFromVal (caseVals));
3256 trueLabel = newiTempLabel (buffer);
3258 ic = newiCodeCondition (compare, trueLabel, NULL);
3260 caseVals = caseVals->next;
3265 /* if default is present then goto break else break */
3266 if (tree->values.switchVals.swDefault)
3268 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3272 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3275 falseLabel = newiTempLabel (buffer);
3276 geniCodeGoto (falseLabel);
3279 ast2iCode (tree->right,lvl+1);
3282 /*-----------------------------------------------------------------*/
3283 /* geniCodeInline - intermediate code for inline assembler */
3284 /*-----------------------------------------------------------------*/
3286 geniCodeInline (ast * tree)
3290 ic = newiCode (INLINEASM, NULL, NULL);
3291 IC_INLINE (ic) = tree->values.inlineasm;
3295 /*-----------------------------------------------------------------*/
3296 /* geniCodeArrayInit - intermediate code for array initializer */
3297 /*-----------------------------------------------------------------*/
3299 geniCodeArrayInit (ast * tree, operand *array)
3303 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3304 ic = newiCode (ARRAYINIT, array, NULL);
3305 IC_ARRAYILIST (ic) = tree->values.constlist;
3307 operand *left=newOperand(), *right=newOperand();
3308 left->type=right->type=SYMBOL;
3309 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3310 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3311 ic = newiCode (ARRAYINIT, left, right);
3316 /*-----------------------------------------------------------------*/
3317 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3318 /* particular case. Ie : assigning or dereferencing array or ptr */
3319 /*-----------------------------------------------------------------*/
3320 set * lvaluereqSet = NULL;
3321 typedef struct lvalItem
3328 /*-----------------------------------------------------------------*/
3329 /* addLvaluereq - add a flag for lvalreq for current ast level */
3330 /*-----------------------------------------------------------------*/
3331 void addLvaluereq(int lvl)
3333 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3336 addSetHead(&lvaluereqSet,lpItem);
3339 /*-----------------------------------------------------------------*/
3340 /* delLvaluereq - del a flag for lvalreq for current ast level */
3341 /*-----------------------------------------------------------------*/
3345 lpItem = getSet(&lvaluereqSet);
3346 if(lpItem) Safe_free(lpItem);
3348 /*-----------------------------------------------------------------*/
3349 /* clearLvaluereq - clear lvalreq flag */
3350 /*-----------------------------------------------------------------*/
3351 void clearLvaluereq()
3354 lpItem = peekSet(lvaluereqSet);
3355 if(lpItem) lpItem->req = 0;
3357 /*-----------------------------------------------------------------*/
3358 /* getLvaluereq - get the last lvalreq level */
3359 /*-----------------------------------------------------------------*/
3360 int getLvaluereqLvl()
3363 lpItem = peekSet(lvaluereqSet);
3364 if(lpItem) return lpItem->lvl;
3367 /*-----------------------------------------------------------------*/
3368 /* isLvaluereq - is lvalreq valid for this level ? */
3369 /*-----------------------------------------------------------------*/
3370 int isLvaluereq(int lvl)
3373 lpItem = peekSet(lvaluereqSet);
3374 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3378 /*-----------------------------------------------------------------*/
3379 /* ast2iCode - creates an icodeList from an ast */
3380 /*-----------------------------------------------------------------*/
3382 ast2iCode (ast * tree,int lvl)
3384 operand *left = NULL;
3385 operand *right = NULL;
3389 /* set the global variables for filename & line number */
3391 filename = tree->filename;
3393 lineno = tree->lineno;
3395 block = tree->block;
3397 scopeLevel = tree->level;
3399 if (tree->type == EX_VALUE)
3400 return operandFromValue (tree->opval.val);
3402 if (tree->type == EX_LINK)
3403 return operandFromLink (tree->opval.lnk);
3405 /* if we find a nullop */
3406 if (tree->type == EX_OP &&
3407 (tree->opval.op == NULLOP ||
3408 tree->opval.op == BLOCK))
3410 ast2iCode (tree->left,lvl+1);
3411 ast2iCode (tree->right,lvl+1);
3415 /* special cases for not evaluating */
3416 if (tree->opval.op != ':' &&
3417 tree->opval.op != '?' &&
3418 tree->opval.op != CALL &&
3419 tree->opval.op != IFX &&
3420 tree->opval.op != LABEL &&
3421 tree->opval.op != GOTO &&
3422 tree->opval.op != SWITCH &&
3423 tree->opval.op != FUNCTION &&
3424 tree->opval.op != INLINEASM)
3427 if (IS_ASSIGN_OP (tree->opval.op) ||
3428 IS_DEREF_OP (tree) ||
3429 (tree->opval.op == '&' && !tree->right) ||
3430 tree->opval.op == PTR_OP)
3433 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3434 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3437 left = operandFromAst (tree->left,lvl);
3439 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3440 left = geniCodeRValue (left, TRUE);
3444 left = operandFromAst (tree->left,lvl);
3446 if (tree->opval.op == INC_OP ||
3447 tree->opval.op == DEC_OP)
3450 right = operandFromAst (tree->right,lvl);
3455 right = operandFromAst (tree->right,lvl);
3459 /* now depending on the type of operand */
3460 /* this will be a biggy */
3461 switch (tree->opval.op)
3464 case '[': /* array operation */
3466 //sym_link *ltype = operandType (left);
3467 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3468 left = geniCodeRValue (left, FALSE);
3469 right = geniCodeRValue (right, TRUE);
3472 return geniCodeArray (left, right,lvl);
3474 case '.': /* structure dereference */
3475 if (IS_PTR (operandType (left)))
3476 left = geniCodeRValue (left, TRUE);
3478 left = geniCodeRValue (left, FALSE);
3480 return geniCodeStruct (left, right, tree->lvalue);
3482 case PTR_OP: /* structure pointer dereference */
3485 pType = operandType (left);
3486 left = geniCodeRValue (left, TRUE);
3488 setOClass (pType, getSpec (operandType (left)));
3491 return geniCodeStruct (left, right, tree->lvalue);
3493 case INC_OP: /* increment operator */
3495 return geniCodePostInc (left);
3497 return geniCodePreInc (right);
3499 case DEC_OP: /* decrement operator */
3501 return geniCodePostDec (left);
3503 return geniCodePreDec (right);
3505 case '&': /* bitwise and or address of operator */
3507 { /* this is a bitwise operator */
3508 left = geniCodeRValue (left, FALSE);
3509 right = geniCodeRValue (right, FALSE);
3510 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3513 return geniCodeAddressOf (left);
3515 case '|': /* bitwise or & xor */
3517 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3518 geniCodeRValue (right, FALSE),
3523 return geniCodeDivision (geniCodeRValue (left, FALSE),
3524 geniCodeRValue (right, FALSE));
3527 return geniCodeModulus (geniCodeRValue (left, FALSE),
3528 geniCodeRValue (right, FALSE));
3531 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3532 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3534 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3538 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3539 geniCodeRValue (right, FALSE));
3541 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3545 return geniCodeAdd (geniCodeRValue (left, FALSE),
3546 geniCodeRValue (right, FALSE),lvl);
3548 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3551 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3552 geniCodeRValue (right, FALSE));
3555 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3556 geniCodeRValue (right, FALSE));
3558 return geniCodeCast (operandType (left),
3559 geniCodeRValue (right, FALSE), FALSE);
3565 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3569 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3570 setOperandType (op, UCHARTYPE);
3581 return geniCodeLogic (geniCodeRValue (left, FALSE),
3582 geniCodeRValue (right, FALSE),
3585 return geniCodeConditional (tree,lvl);
3588 return operandFromLit (getSize (tree->right->ftype));
3592 sym_link *rtype = operandType (right);
3593 sym_link *ltype = operandType (left);
3594 if (IS_PTR (rtype) && IS_ITEMP (right)
3595 && right->isaddr && compareType (rtype->next, ltype) == 1)
3596 right = geniCodeRValue (right, TRUE);
3598 right = geniCodeRValue (right, FALSE);
3600 geniCodeAssign (left, right, 0);
3605 geniCodeAssign (left,
3606 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3608 geniCodeRValue (right, FALSE),FALSE), 0);
3612 geniCodeAssign (left,
3613 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3615 geniCodeRValue (right, FALSE)), 0);
3618 geniCodeAssign (left,
3619 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3621 geniCodeRValue (right, FALSE)), 0);
3624 sym_link *rtype = operandType (right);
3625 sym_link *ltype = operandType (left);
3626 if (IS_PTR (rtype) && IS_ITEMP (right)
3627 && right->isaddr && compareType (rtype->next, ltype) == 1)
3628 right = geniCodeRValue (right, TRUE);
3630 right = geniCodeRValue (right, FALSE);
3633 return geniCodeAssign (left,
3634 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3640 sym_link *rtype = operandType (right);
3641 sym_link *ltype = operandType (left);
3642 if (IS_PTR (rtype) && IS_ITEMP (right)
3643 && right->isaddr && compareType (rtype->next, ltype) == 1)
3645 right = geniCodeRValue (right, TRUE);
3649 right = geniCodeRValue (right, FALSE);
3652 geniCodeAssign (left,
3653 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3659 geniCodeAssign (left,
3660 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3662 geniCodeRValue (right, FALSE)), 0);
3665 geniCodeAssign (left,
3666 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3668 geniCodeRValue (right, FALSE)), 0);
3671 geniCodeAssign (left,
3672 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3674 geniCodeRValue (right, FALSE),
3676 operandType (left)), 0);
3679 geniCodeAssign (left,
3680 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3682 geniCodeRValue (right, FALSE),
3684 operandType (left)), 0);
3687 geniCodeAssign (left,
3688 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3690 geniCodeRValue (right, FALSE),
3692 operandType (left)), 0);
3694 return geniCodeRValue (right, FALSE);
3697 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3700 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3701 return ast2iCode (tree->right,lvl+1);
3704 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3705 return ast2iCode (tree->right,lvl+1);
3708 geniCodeFunctionBody (tree,lvl);
3712 geniCodeReturn (right);
3716 geniCodeIfx (tree,lvl);
3720 geniCodeSwitch (tree,lvl);
3724 geniCodeInline (tree);
3728 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3735 /*-----------------------------------------------------------------*/
3736 /* reverseICChain - gets from the list and creates a linkedlist */
3737 /*-----------------------------------------------------------------*/
3744 while ((loop = getSet (&iCodeChain)))
3756 /*-----------------------------------------------------------------*/
3757 /* iCodeFromAst - given an ast will convert it to iCode */
3758 /*-----------------------------------------------------------------*/
3760 iCodeFromAst (ast * tree)
3762 returnLabel = newiTempLabel ("_return");
3763 entryLabel = newiTempLabel ("_entry");
3765 return reverseiCChain ();
3768 static const char *opTypeToStr(OPTYPE op)
3772 case SYMBOL: return "symbol";
3773 case VALUE: return "value";
3774 case TYPE: return "type";
3776 return "undefined type";
3780 operand *validateOpType(operand *op,
3787 if (op && op->type == type)
3792 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3793 " expected %s, got %s\n",
3794 macro, args, file, line,
3795 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3797 return op; // never reached, makes compiler happy.