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);
1530 /* Just to keep the compiler happy */
1531 return (operand *) 0;
1534 /*-----------------------------------------------------------------*/
1535 /* setOperandType - sets the operand's type to the given type */
1536 /*-----------------------------------------------------------------*/
1538 setOperandType (operand * op, sym_link * type)
1540 /* depending on the type of operand */
1545 op->operand.valOperand->etype =
1546 getSpec (op->operand.valOperand->type =
1547 copyLinkChain (type));
1551 if (op->operand.symOperand->isitmp)
1552 op->operand.symOperand->etype =
1553 getSpec (op->operand.symOperand->type =
1554 copyLinkChain (type));
1556 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1557 "attempt to modify type of source");
1561 op->operand.typeOperand = copyLinkChain (type);
1566 /*-----------------------------------------------------------------*/
1567 /* Get size in byte of ptr need to access an array */
1568 /*-----------------------------------------------------------------*/
1570 getArraySizePtr (operand * op)
1572 sym_link *ltype = operandType(op);
1576 int size = getSize(ltype);
1577 return(IS_GENPTR(ltype)?(size-1):size);
1582 sym_link *letype = getSpec(ltype);
1583 switch (PTR_TYPE (SPEC_OCLS (letype)))
1595 return (GPTRSIZE-1);
1604 /*-----------------------------------------------------------------*/
1605 /* perform "usual unary conversions" */
1606 /*-----------------------------------------------------------------*/
1608 usualUnaryConversions (operand * op)
1610 if (IS_INTEGRAL (operandType (op)))
1612 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1615 return geniCodeCast (INTTYPE, op, TRUE);
1621 /*-----------------------------------------------------------------*/
1622 /* perform "usual binary conversions" */
1623 /*-----------------------------------------------------------------*/
1625 usualBinaryConversions (operand ** op1, operand ** op2)
1628 sym_link *rtype = operandType (*op2);
1629 sym_link *ltype = operandType (*op1);
1631 ctype = computeType (ltype, rtype);
1633 *op1 = geniCodeCast (ctype, *op1, TRUE);
1634 *op2 = geniCodeCast (ctype, *op2, TRUE);
1639 /*-----------------------------------------------------------------*/
1640 /* geniCodeValueAtAddress - generate intermeditate code for value */
1642 /*-----------------------------------------------------------------*/
1644 geniCodeRValue (operand * op, bool force)
1647 sym_link *type = operandType (op);
1648 sym_link *etype = getSpec (type);
1650 /* if this is an array & already */
1651 /* an address then return this */
1652 if (IS_AGGREGATE (type) ||
1653 (IS_PTR (type) && !force && !op->isaddr))
1654 return operandFromOperand (op);
1656 /* if this is not an address then must be */
1657 /* rvalue already so return this one */
1661 /* if this is not a temp symbol then */
1662 if (!IS_ITEMP (op) &&
1664 !IN_FARSPACE (SPEC_OCLS (etype)))
1666 op = operandFromOperand (op);
1671 if (IS_SPEC (type) &&
1672 IS_TRUE_SYMOP (op) &&
1673 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1674 (options.model == MODEL_FLAT24) ))
1676 op = operandFromOperand (op);
1681 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1682 if (IS_PTR (type) && op->isaddr && force)
1685 type = copyLinkChain (type);
1687 IC_RESULT (ic) = newiTempOperand (type, 1);
1688 IC_RESULT (ic)->isaddr = 0;
1690 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1694 return IC_RESULT (ic);
1697 /*-----------------------------------------------------------------*/
1698 /* geniCodeCast - changes the value from one type to another */
1699 /*-----------------------------------------------------------------*/
1701 geniCodeCast (sym_link * type, operand * op, bool implicit)
1705 sym_link *opetype = getSpec (optype = operandType (op));
1709 /* one of them has size zero then error */
1710 if (IS_VOID (optype))
1712 werror (E_CAST_ZERO);
1716 /* if the operand is already the desired type then do nothing */
1717 if (compareType (type, optype) == 1)
1720 /* if this is a literal then just change the type & return */
1721 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1722 return operandFromValue (valCastLiteral (type,
1723 operandLitValue (op)));
1725 /* if casting to/from pointers, do some checking */
1726 if (IS_PTR(type)) { // to a pointer
1727 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1728 if (IS_INTEGRAL(optype)) {
1729 // maybe this is NULL, than it's ok.
1730 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1731 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1732 // no way to set the storage
1733 if (IS_LITERAL(optype)) {
1734 werror(E_LITERAL_GENERIC);
1737 werror(E_NONPTR2_GENPTR);
1740 } else if (implicit) {
1741 werror(W_INTEGRAL2PTR_NOCAST);
1746 // shouldn't do that with float, array or structure unless to void
1747 if (!IS_VOID(getSpec(type)) &&
1748 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1749 werror(E_INCOMPAT_TYPES);
1753 } else { // from a pointer to a pointer
1754 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1755 // if not a pointer to a function
1756 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1757 if (implicit) { // if not to generic, they have to match
1758 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1759 werror(E_INCOMPAT_PTYPES);
1766 } else { // to a non pointer
1767 if (IS_PTR(optype)) { // from a pointer
1768 if (implicit) { // sneaky
1769 if (IS_INTEGRAL(type)) {
1770 werror(W_PTR2INTEGRAL_NOCAST);
1772 } else { // shouldn't do that with float, array or structure
1773 werror(E_INCOMPAT_TYPES);
1780 printFromToType (optype, type);
1783 /* if they are the same size create an assignment */
1784 if (getSize (type) == getSize (optype) &&
1785 !IS_BITFIELD (type) &&
1787 !IS_FLOAT (optype) &&
1788 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1789 (!IS_SPEC (type) && !IS_SPEC (optype))))
1792 ic = newiCode ('=', NULL, op);
1793 IC_RESULT (ic) = newiTempOperand (type, 0);
1794 SPIL_LOC (IC_RESULT (ic)) =
1795 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1796 IC_RESULT (ic)->isaddr = 0;
1800 ic = newiCode (CAST, operandFromLink (type),
1801 geniCodeRValue (op, FALSE));
1803 IC_RESULT (ic) = newiTempOperand (type, 0);
1806 /* preserve the storage class & output class */
1807 /* of the original variable */
1808 restype = getSpec (operandType (IC_RESULT (ic)));
1809 if (!IS_LITERAL(opetype))
1810 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1811 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1814 return IC_RESULT (ic);
1817 /*-----------------------------------------------------------------*/
1818 /* geniCodeLabel - will create a Label */
1819 /*-----------------------------------------------------------------*/
1821 geniCodeLabel (symbol * label)
1825 ic = newiCodeLabelGoto (LABEL, label);
1829 /*-----------------------------------------------------------------*/
1830 /* geniCodeGoto - will create a Goto */
1831 /*-----------------------------------------------------------------*/
1833 geniCodeGoto (symbol * label)
1837 ic = newiCodeLabelGoto (GOTO, label);
1841 /*-----------------------------------------------------------------*/
1842 /* geniCodeMultiply - gen intermediate code for multiplication */
1843 /*-----------------------------------------------------------------*/
1845 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1852 /* if they are both literal then we know the result */
1853 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1854 return operandFromValue (valMult (left->operand.valOperand,
1855 right->operand.valOperand));
1857 if (IS_LITERAL(retype)) {
1858 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1861 resType = usualBinaryConversions (&left, &right);
1863 rtype = operandType (right);
1864 retype = getSpec (rtype);
1865 ltype = operandType (left);
1866 letype = getSpec (ltype);
1870 SPEC_NOUN(getSpec(resType))=V_INT;
1873 /* if the right is a literal & power of 2 */
1874 /* then make it a left shift */
1875 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1876 efficient in most cases than 2 bytes result = 2 bytes << literal
1877 if port has 1 byte muldiv */
1878 if (p2 && !IS_FLOAT (letype) &&
1879 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1880 (port->support.muldiv == 1)))
1882 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1884 /* LEFT_OP need same size for left and result, */
1885 left = geniCodeCast (resType, left, TRUE);
1886 ltype = operandType (left);
1888 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1892 ic = newiCode ('*', left, right); /* normal multiplication */
1893 /* if the size left or right > 1 then support routine */
1894 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1898 IC_RESULT (ic) = newiTempOperand (resType, 1);
1901 return IC_RESULT (ic);
1904 /*-----------------------------------------------------------------*/
1905 /* geniCodeDivision - gen intermediate code for division */
1906 /*-----------------------------------------------------------------*/
1908 geniCodeDivision (operand * left, operand * right)
1913 sym_link *rtype = operandType (right);
1914 sym_link *retype = getSpec (rtype);
1915 sym_link *ltype = operandType (left);
1916 sym_link *letype = getSpec (ltype);
1918 resType = usualBinaryConversions (&left, &right);
1920 /* if the right is a literal & power of 2
1921 and left is unsigned then make it a
1923 if (IS_LITERAL (retype) &&
1924 !IS_FLOAT (letype) &&
1925 SPEC_USIGN(letype) &&
1926 (p2 = powof2 ((unsigned long)
1927 floatFromVal (right->operand.valOperand)))) {
1928 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1932 ic = newiCode ('/', left, right); /* normal division */
1933 /* if the size left or right > 1 then support routine */
1934 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1937 IC_RESULT (ic) = newiTempOperand (resType, 0);
1940 return IC_RESULT (ic);
1942 /*-----------------------------------------------------------------*/
1943 /* geniCodeModulus - gen intermediate code for modulus */
1944 /*-----------------------------------------------------------------*/
1946 geniCodeModulus (operand * left, operand * right)
1952 /* if they are both literal then we know the result */
1953 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1954 return operandFromValue (valMod (left->operand.valOperand,
1955 right->operand.valOperand));
1957 resType = usualBinaryConversions (&left, &right);
1959 /* now they are the same size */
1960 ic = newiCode ('%', left, right);
1962 /* if the size left or right > 1 then support routine */
1963 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1965 IC_RESULT (ic) = newiTempOperand (resType, 0);
1968 return IC_RESULT (ic);
1971 /*-----------------------------------------------------------------*/
1972 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1973 /*-----------------------------------------------------------------*/
1975 geniCodePtrPtrSubtract (operand * left, operand * right)
1981 /* if they are both literals then */
1982 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1984 result = operandFromValue (valMinus (left->operand.valOperand,
1985 right->operand.valOperand));
1989 ic = newiCode ('-', left, right);
1991 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1995 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1999 // should we really do this? is this ANSI?
2000 return geniCodeDivision (result,
2001 operandFromLit (getSize (ltype->next)));
2004 /*-----------------------------------------------------------------*/
2005 /* geniCodeSubtract - generates code for subtraction */
2006 /*-----------------------------------------------------------------*/
2008 geniCodeSubtract (operand * left, operand * right)
2015 /* if they both pointers then */
2016 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2017 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2018 return geniCodePtrPtrSubtract (left, right);
2020 /* if they are both literal then we know the result */
2021 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2022 && left->isLiteral && right->isLiteral)
2023 return operandFromValue (valMinus (left->operand.valOperand,
2024 right->operand.valOperand));
2026 /* if left is an array or pointer */
2027 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2029 isarray = left->isaddr;
2030 right = geniCodeMultiply (right,
2031 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2032 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2035 { /* make them the same size */
2036 resType = usualBinaryConversions (&left, &right);
2039 ic = newiCode ('-', left, right);
2041 IC_RESULT (ic) = newiTempOperand (resType, 1);
2042 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2044 /* if left or right is a float */
2045 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2049 return IC_RESULT (ic);
2052 /*-----------------------------------------------------------------*/
2053 /* geniCodeAdd - generates iCode for addition */
2054 /*-----------------------------------------------------------------*/
2056 geniCodeAdd (operand * left, operand * right, int lvl)
2064 /* if the right side is LITERAL zero */
2065 /* return the left side */
2066 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2069 /* if left is literal zero return right */
2070 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2073 /* if left is a pointer then size */
2074 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2076 isarray = left->isaddr;
2077 // there is no need to multiply with 1
2078 if (getSize(ltype->next)!=1) {
2079 size = operandFromLit (getSize (ltype->next));
2080 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2082 resType = copyLinkChain (ltype);
2085 { // make them the same size
2086 resType = usualBinaryConversions (&left, &right);
2089 /* if they are both literals then we know */
2090 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2091 && left->isLiteral && right->isLiteral)
2092 return operandFromValue (valPlus (valFromType (letype),
2093 valFromType (retype)));
2095 ic = newiCode ('+', left, right);
2097 IC_RESULT (ic) = newiTempOperand (resType, 1);
2098 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2100 /* if left or right is a float then support
2102 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2107 return IC_RESULT (ic);
2111 /*-----------------------------------------------------------------*/
2112 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2113 /*-----------------------------------------------------------------*/
2115 aggrToPtr (sym_link * type, bool force)
2121 if (IS_PTR (type) && !force)
2124 etype = getSpec (type);
2125 ptype = newLink (DECLARATOR);
2129 /* if the output class is code */
2130 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2131 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2133 /* if the variable was declared a constant */
2134 /* then the pointer points to a constant */
2135 if (IS_CONSTANT (etype))
2136 DCL_PTR_CONST (ptype) = 1;
2138 /* the variable was volatile then pointer to volatile */
2139 if (IS_VOLATILE (etype))
2140 DCL_PTR_VOLATILE (ptype) = 1;
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodeArray2Ptr - array to pointer */
2147 /*-----------------------------------------------------------------*/
2149 geniCodeArray2Ptr (operand * op)
2151 sym_link *optype = operandType (op);
2152 sym_link *opetype = getSpec (optype);
2154 /* set the pointer depending on the storage class */
2155 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2156 DCL_PTR_CONST (optype) = port->mem.code_ro;
2158 /* if the variable was declared a constant */
2159 /* then the pointer points to a constant */
2160 if (IS_CONSTANT (opetype))
2161 DCL_PTR_CONST (optype) = 1;
2163 /* the variable was volatile then pointer to volatile */
2164 if (IS_VOLATILE (opetype))
2165 DCL_PTR_VOLATILE (optype) = 1;
2172 /*-----------------------------------------------------------------*/
2173 /* geniCodeArray - array access */
2174 /*-----------------------------------------------------------------*/
2176 geniCodeArray (operand * left, operand * right,int lvl)
2179 sym_link *ltype = operandType (left);
2183 if (IS_PTR (ltype->next) && left->isaddr)
2185 left = geniCodeRValue (left, FALSE);
2187 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2190 right = geniCodeMultiply (right,
2191 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2193 /* we can check for limits here */
2194 if (isOperandLiteral (right) &&
2197 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2199 werror (E_ARRAY_BOUND);
2200 right = operandFromLit (0);
2203 ic = newiCode ('+', left, right);
2205 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2206 !IS_AGGREGATE (ltype->next) &&
2207 !IS_PTR (ltype->next))
2208 ? ltype : ltype->next), 0);
2210 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2212 return IC_RESULT (ic);
2215 /*-----------------------------------------------------------------*/
2216 /* geniCodeStruct - generates intermediate code for structres */
2217 /*-----------------------------------------------------------------*/
2219 geniCodeStruct (operand * left, operand * right, bool islval)
2222 sym_link *type = operandType (left);
2223 sym_link *etype = getSpec (type);
2225 symbol *element = getStructElement (SPEC_STRUCT (etype),
2226 right->operand.symOperand);
2228 wassert(IS_SYMOP(right));
2230 /* add the offset */
2231 ic = newiCode ('+', left, operandFromLit (element->offset));
2233 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2235 /* preserve the storage & output class of the struct */
2236 /* as well as the volatile attribute */
2237 retype = getSpec (operandType (IC_RESULT (ic)));
2238 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2239 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2240 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2242 if (IS_PTR (element->type))
2243 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2245 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2249 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2252 /*-----------------------------------------------------------------*/
2253 /* geniCodePostInc - generate int code for Post increment */
2254 /*-----------------------------------------------------------------*/
2256 geniCodePostInc (operand * op)
2260 sym_link *optype = operandType (op);
2262 operand *rv = (IS_ITEMP (op) ?
2263 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2265 sym_link *rvtype = operandType (rv);
2268 /* if this is not an address we have trouble */
2271 werror (E_LVALUE_REQUIRED, "++");
2275 rOp = newiTempOperand (rvtype, 0);
2276 OP_SYMBOL(rOp)->noSpilLoc = 1;
2279 OP_SYMBOL(rv)->noSpilLoc = 1;
2281 geniCodeAssign (rOp, rv, 0);
2283 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2284 if (IS_FLOAT (rvtype))
2285 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2287 ic = newiCode ('+', rv, operandFromLit (size));
2289 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2292 geniCodeAssign (op, result, 0);
2298 /*-----------------------------------------------------------------*/
2299 /* geniCodePreInc - generate code for preIncrement */
2300 /*-----------------------------------------------------------------*/
2302 geniCodePreInc (operand * op)
2305 sym_link *optype = operandType (op);
2306 operand *rop = (IS_ITEMP (op) ?
2307 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2309 sym_link *roptype = operandType (rop);
2315 werror (E_LVALUE_REQUIRED, "++");
2320 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2321 if (IS_FLOAT (roptype))
2322 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2324 ic = newiCode ('+', rop, operandFromLit (size));
2325 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2329 return geniCodeAssign (op, result, 0);
2332 /*-----------------------------------------------------------------*/
2333 /* geniCodePostDec - generates code for Post decrement */
2334 /*-----------------------------------------------------------------*/
2336 geniCodePostDec (operand * op)
2340 sym_link *optype = operandType (op);
2342 operand *rv = (IS_ITEMP (op) ?
2343 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2345 sym_link *rvtype = operandType (rv);
2348 /* if this is not an address we have trouble */
2351 werror (E_LVALUE_REQUIRED, "--");
2355 rOp = newiTempOperand (rvtype, 0);
2356 OP_SYMBOL(rOp)->noSpilLoc = 1;
2359 OP_SYMBOL(rv)->noSpilLoc = 1;
2361 geniCodeAssign (rOp, rv, 0);
2363 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2364 if (IS_FLOAT (rvtype))
2365 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2367 ic = newiCode ('-', rv, operandFromLit (size));
2369 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2372 geniCodeAssign (op, result, 0);
2378 /*-----------------------------------------------------------------*/
2379 /* geniCodePreDec - generate code for pre decrement */
2380 /*-----------------------------------------------------------------*/
2382 geniCodePreDec (operand * op)
2385 sym_link *optype = operandType (op);
2386 operand *rop = (IS_ITEMP (op) ?
2387 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2389 sym_link *roptype = operandType (rop);
2395 werror (E_LVALUE_REQUIRED, "--");
2400 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2401 if (IS_FLOAT (roptype))
2402 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2404 ic = newiCode ('-', rop, operandFromLit (size));
2405 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2409 return geniCodeAssign (op, result, 0);
2413 /*-----------------------------------------------------------------*/
2414 /* geniCodeBitwise - gen int code for bitWise operators */
2415 /*-----------------------------------------------------------------*/
2417 geniCodeBitwise (operand * left, operand * right,
2418 int oper, sym_link * resType)
2422 left = geniCodeCast (resType, left, TRUE);
2423 right = geniCodeCast (resType, right, TRUE);
2425 ic = newiCode (oper, left, right);
2426 IC_RESULT (ic) = newiTempOperand (resType, 0);
2429 return IC_RESULT (ic);
2432 /*-----------------------------------------------------------------*/
2433 /* geniCodeAddressOf - gens icode for '&' address of operator */
2434 /*-----------------------------------------------------------------*/
2436 geniCodeAddressOf (operand * op)
2440 sym_link *optype = operandType (op);
2441 sym_link *opetype = getSpec (optype);
2443 /* lvalue check already done in decorateType */
2444 /* this must be a lvalue */
2445 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2446 /* werror (E_LVALUE_REQUIRED,"&"); */
2450 p = newLink (DECLARATOR);
2452 /* set the pointer depending on the storage class */
2453 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2454 DCL_PTR_CONST (p) = port->mem.code_ro;
2456 /* make sure we preserve the const & volatile */
2457 if (IS_CONSTANT (opetype))
2458 DCL_PTR_CONST (p) = 1;
2460 if (IS_VOLATILE (opetype))
2461 DCL_PTR_VOLATILE (p) = 1;
2463 p->next = copyLinkChain (optype);
2465 /* if already a temp */
2468 setOperandType (op, p);
2473 /* other wise make this of the type coming in */
2474 ic = newiCode (ADDRESS_OF, op, NULL);
2475 IC_RESULT (ic) = newiTempOperand (p, 1);
2476 IC_RESULT (ic)->isaddr = 0;
2478 return IC_RESULT (ic);
2480 /*-----------------------------------------------------------------*/
2481 /* setOClass - sets the output class depending on the pointer type */
2482 /*-----------------------------------------------------------------*/
2484 setOClass (sym_link * ptr, sym_link * spec)
2486 switch (DCL_TYPE (ptr))
2489 SPEC_OCLS (spec) = data;
2493 SPEC_OCLS (spec) = generic;
2497 SPEC_OCLS (spec) = xdata;
2501 SPEC_OCLS (spec) = code;
2505 SPEC_OCLS (spec) = idata;
2509 SPEC_OCLS (spec) = xstack;
2513 SPEC_OCLS (spec) = eeprom;
2522 /*-----------------------------------------------------------------*/
2523 /* geniCodeDerefPtr - dereference pointer with '*' */
2524 /*-----------------------------------------------------------------*/
2526 geniCodeDerefPtr (operand * op,int lvl)
2528 sym_link *rtype, *retype;
2529 sym_link *optype = operandType (op);
2531 // if this is an array then array access
2532 if (IS_ARRAY (optype)) {
2533 // don't worry, this will be optimized out later
2534 return geniCodeArray (op, operandFromLit (0), lvl);
2537 // just in case someone screws up
2538 wassert (IS_PTR (optype));
2540 if (IS_TRUE_SYMOP (op))
2543 op = geniCodeRValue (op, TRUE);
2546 /* now get rid of the pointer part */
2547 if (isLvaluereq(lvl) && IS_ITEMP (op))
2549 retype = getSpec (rtype = copyLinkChain (optype));
2553 retype = getSpec (rtype = copyLinkChain (optype->next));
2556 /* outputclass needs 2b updated */
2557 setOClass (optype, retype);
2559 op->isGptr = IS_GENPTR (optype);
2561 /* if the pointer was declared as a constant */
2562 /* then we cannot allow assignment to the derefed */
2563 if (IS_PTR_CONST (optype))
2564 SPEC_CONST (retype) = 1;
2566 op->isaddr = (IS_PTR (rtype) ||
2567 IS_STRUCT (rtype) ||
2572 if (!isLvaluereq(lvl))
2573 op = geniCodeRValue (op, TRUE);
2575 setOperandType (op, rtype);
2580 /*-----------------------------------------------------------------*/
2581 /* geniCodeUnaryMinus - does a unary minus of the operand */
2582 /*-----------------------------------------------------------------*/
2584 geniCodeUnaryMinus (operand * op)
2587 sym_link *optype = operandType (op);
2589 if (IS_LITERAL (optype))
2590 return operandFromLit (-floatFromVal (op->operand.valOperand));
2592 ic = newiCode (UNARYMINUS, op, NULL);
2593 IC_RESULT (ic) = newiTempOperand (optype, 0);
2595 return IC_RESULT (ic);
2598 /*-----------------------------------------------------------------*/
2599 /* geniCodeLeftShift - gen i code for left shift */
2600 /*-----------------------------------------------------------------*/
2602 geniCodeLeftShift (operand * left, operand * right)
2606 ic = newiCode (LEFT_OP, left, right);
2607 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2609 return IC_RESULT (ic);
2612 /*-----------------------------------------------------------------*/
2613 /* geniCodeRightShift - gen i code for right shift */
2614 /*-----------------------------------------------------------------*/
2616 geniCodeRightShift (operand * left, operand * right)
2620 ic = newiCode (RIGHT_OP, left, right);
2621 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2623 return IC_RESULT (ic);
2626 /*-----------------------------------------------------------------*/
2627 /* geniCodeLogic- logic code */
2628 /*-----------------------------------------------------------------*/
2630 geniCodeLogic (operand * left, operand * right, int op)
2634 sym_link *rtype = operandType (right);
2635 sym_link *ltype = operandType (left);
2637 /* left is integral type and right is literal then
2638 check if the literal value is within bounds */
2639 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2641 checkConstantRange(ltype,
2642 OP_VALUE(right), "compare operation", 1);
2645 ctype = usualBinaryConversions (&left, &right);
2647 ic = newiCode (op, left, right);
2648 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2650 /* if comparing float
2651 and not a '==' || '!=' || '&&' || '||' (these
2653 if (IS_FLOAT(ctype) &&
2661 return IC_RESULT (ic);
2664 /*-----------------------------------------------------------------*/
2665 /* geniCodeUnary - for a a generic unary operation */
2666 /*-----------------------------------------------------------------*/
2668 geniCodeUnary (operand * op, int oper)
2670 iCode *ic = newiCode (oper, op, NULL);
2672 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2674 return IC_RESULT (ic);
2677 /*-----------------------------------------------------------------*/
2678 /* geniCodeConditional - geniCode for '?' ':' operation */
2679 /*-----------------------------------------------------------------*/
2681 geniCodeConditional (ast * tree,int lvl)
2684 symbol *falseLabel = newiTempLabel (NULL);
2685 symbol *exitLabel = newiTempLabel (NULL);
2686 operand *cond = ast2iCode (tree->left,lvl+1);
2687 operand *true, *false, *result;
2689 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2693 true = ast2iCode (tree->right->left,lvl+1);
2695 /* move the value to a new Operand */
2696 result = newiTempOperand (tree->right->ftype, 0);
2697 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2699 /* generate an unconditional goto */
2700 geniCodeGoto (exitLabel);
2702 /* now for the right side */
2703 geniCodeLabel (falseLabel);
2705 false = ast2iCode (tree->right->right,lvl+1);
2706 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2708 /* create the exit label */
2709 geniCodeLabel (exitLabel);
2714 /*-----------------------------------------------------------------*/
2715 /* geniCodeAssign - generate code for assignment */
2716 /*-----------------------------------------------------------------*/
2718 geniCodeAssign (operand * left, operand * right, int nosupdate)
2721 sym_link *ltype = operandType (left);
2722 sym_link *rtype = operandType (right);
2724 if (!left->isaddr && !IS_ITEMP (left))
2726 werror (E_LVALUE_REQUIRED, "assignment");
2730 /* left is integral type and right is literal then
2731 check if the literal value is within bounds */
2732 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2734 checkConstantRange(ltype,
2735 OP_VALUE(right), "= operation", 0);
2738 /* if the left & right type don't exactly match */
2739 /* if pointer set then make sure the check is
2740 done with the type & not the pointer */
2741 /* then cast rights type to left */
2743 /* first check the type for pointer assignement */
2744 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2745 compareType (ltype, rtype) <= 0)
2747 if (compareType (ltype->next, rtype) < 0)
2748 right = geniCodeCast (ltype->next, right, TRUE);
2750 else if (compareType (ltype, rtype) < 0)
2751 right = geniCodeCast (ltype, right, TRUE);
2753 /* if left is a true symbol & ! volatile
2754 create an assignment to temporary for
2755 the right & then assign this temporary
2756 to the symbol this is SSA . isn't it simple
2757 and folks have published mountains of paper on it */
2758 if (IS_TRUE_SYMOP (left) &&
2759 !isOperandVolatile (left, FALSE) &&
2760 isOperandGlobal (left))
2764 if (IS_TRUE_SYMOP (right))
2765 sym = OP_SYMBOL (right);
2766 ic = newiCode ('=', NULL, right);
2767 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2768 SPIL_LOC (right) = sym;
2772 ic = newiCode ('=', NULL, right);
2773 IC_RESULT (ic) = left;
2776 /* if left isgptr flag is set then support
2777 routine will be required */
2781 ic->nosupdate = nosupdate;
2785 /*-----------------------------------------------------------------*/
2786 /* geniCodeSEParms - generate code for side effecting fcalls */
2787 /*-----------------------------------------------------------------*/
2789 geniCodeSEParms (ast * parms,int lvl)
2794 if (parms->type == EX_OP && parms->opval.op == PARAM)
2796 geniCodeSEParms (parms->left,lvl);
2797 geniCodeSEParms (parms->right,lvl);
2801 /* hack don't like this but too lazy to think of
2803 if (IS_ADDRESS_OF_OP (parms))
2804 parms->left->lvalue = 1;
2806 if (IS_CAST_OP (parms) &&
2807 IS_PTR (parms->ftype) &&
2808 IS_ADDRESS_OF_OP (parms->right))
2809 parms->right->left->lvalue = 1;
2811 parms->opval.oprnd =
2812 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2814 parms->type = EX_OPERAND;
2815 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2816 SPEC_ARGREG(parms->ftype);
2819 /*-----------------------------------------------------------------*/
2820 /* geniCodeParms - generates parameters */
2821 /*-----------------------------------------------------------------*/
2823 geniCodeParms (ast * parms, value *argVals, int *stack,
2824 sym_link * fetype, symbol * func,int lvl)
2832 if (argVals==NULL) {
2834 argVals=FUNC_ARGS(func->type);
2837 /* if this is a param node then do the left & right */
2838 if (parms->type == EX_OP && parms->opval.op == PARAM)
2840 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2841 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2845 /* get the parameter value */
2846 if (parms->type == EX_OPERAND)
2847 pval = parms->opval.oprnd;
2850 /* maybe this else should go away ?? */
2851 /* hack don't like this but too lazy to think of
2853 if (IS_ADDRESS_OF_OP (parms))
2854 parms->left->lvalue = 1;
2856 if (IS_CAST_OP (parms) &&
2857 IS_PTR (parms->ftype) &&
2858 IS_ADDRESS_OF_OP (parms->right))
2859 parms->right->left->lvalue = 1;
2861 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2864 /* if register parm then make it a send */
2865 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2866 IFFUNC_ISBUILTIN(func->type))
2868 ic = newiCode (SEND, pval, NULL);
2869 ic->argreg = SPEC_ARGREG(parms->etype);
2870 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2875 /* now decide whether to push or assign */
2876 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2880 operand *top = operandFromSymbol (argVals->sym);
2881 /* clear useDef and other bitVectors */
2882 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2883 geniCodeAssign (top, pval, 1);
2887 sym_link *p = operandType (pval);
2889 ic = newiCode (IPUSH, pval, NULL);
2891 /* update the stack adjustment */
2892 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2897 argVals=argVals->next;
2901 /*-----------------------------------------------------------------*/
2902 /* geniCodeCall - generates temp code for calling */
2903 /*-----------------------------------------------------------------*/
2905 geniCodeCall (operand * left, ast * parms,int lvl)
2909 sym_link *type, *etype;
2912 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2913 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2914 werror (E_FUNCTION_EXPECTED);
2918 /* take care of parameters with side-effecting
2919 function calls in them, this is required to take care
2920 of overlaying function parameters */
2921 geniCodeSEParms (parms,lvl);
2923 /* first the parameters */
2924 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2926 /* now call : if symbol then pcall */
2927 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2928 ic = newiCode (PCALL, left, NULL);
2930 ic = newiCode (CALL, left, NULL);
2933 type = copyLinkChain (operandType (left)->next);
2934 etype = getSpec (type);
2935 SPEC_EXTR (etype) = 0;
2936 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2940 /* stack adjustment after call */
2941 ic->parmBytes = stack;
2946 /*-----------------------------------------------------------------*/
2947 /* geniCodeReceive - generate intermediate code for "receive" */
2948 /*-----------------------------------------------------------------*/
2950 geniCodeReceive (value * args)
2952 /* for all arguments that are passed in registers */
2956 if (IS_REGPARM (args->etype))
2958 operand *opr = operandFromValue (args);
2960 symbol *sym = OP_SYMBOL (opr);
2963 /* we will use it after all optimizations
2964 and before liveRange calculation */
2965 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2968 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2969 options.stackAuto == 0 &&
2970 (!(options.model == MODEL_FLAT24)) )
2975 opl = newiTempOperand (args->type, 0);
2977 sym->reqv->key = sym->key;
2978 OP_SYMBOL (sym->reqv)->key = sym->key;
2979 OP_SYMBOL (sym->reqv)->isreqv = 1;
2980 OP_SYMBOL (sym->reqv)->islocal = 0;
2981 SPIL_LOC (sym->reqv) = sym;
2985 ic = newiCode (RECEIVE, NULL, NULL);
2986 ic->argreg = SPEC_ARGREG(args->etype);
2988 currFunc->recvSize = getSize (sym->type);
2991 IC_RESULT (ic) = opr;
2999 /*-----------------------------------------------------------------*/
3000 /* geniCodeFunctionBody - create the function body */
3001 /*-----------------------------------------------------------------*/
3003 geniCodeFunctionBody (ast * tree,int lvl)
3010 /* reset the auto generation */
3016 func = ast2iCode (tree->left,lvl+1);
3017 fetype = getSpec (operandType (func));
3019 savelineno = lineno;
3020 lineno = OP_SYMBOL (func)->lineDef;
3021 /* create an entry label */
3022 geniCodeLabel (entryLabel);
3023 lineno = savelineno;
3025 /* create a proc icode */
3026 ic = newiCode (FUNCTION, func, NULL);
3027 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3031 /* for all parameters that are passed
3032 on registers add a "receive" */
3033 geniCodeReceive (tree->values.args);
3035 /* generate code for the body */
3036 ast2iCode (tree->right,lvl+1);
3038 /* create a label for return */
3039 geniCodeLabel (returnLabel);
3041 /* now generate the end proc */
3042 ic = newiCode (ENDFUNCTION, func, NULL);
3047 /*-----------------------------------------------------------------*/
3048 /* geniCodeReturn - gen icode for 'return' statement */
3049 /*-----------------------------------------------------------------*/
3051 geniCodeReturn (operand * op)
3055 /* if the operand is present force an rvalue */
3057 op = geniCodeRValue (op, FALSE);
3059 ic = newiCode (RETURN, op, NULL);
3063 /*-----------------------------------------------------------------*/
3064 /* geniCodeIfx - generates code for extended if statement */
3065 /*-----------------------------------------------------------------*/
3067 geniCodeIfx (ast * tree,int lvl)
3070 operand *condition = ast2iCode (tree->left,lvl+1);
3073 /* if condition is null then exit */
3077 condition = geniCodeRValue (condition, FALSE);
3079 cetype = getSpec (operandType (condition));
3080 /* if the condition is a literal */
3081 if (IS_LITERAL (cetype))
3083 if (floatFromVal (condition->operand.valOperand))
3085 if (tree->trueLabel)
3086 geniCodeGoto (tree->trueLabel);
3092 if (tree->falseLabel)
3093 geniCodeGoto (tree->falseLabel);
3100 if (tree->trueLabel)
3102 ic = newiCodeCondition (condition,
3107 if (tree->falseLabel)
3108 geniCodeGoto (tree->falseLabel);
3112 ic = newiCodeCondition (condition,
3119 ast2iCode (tree->right,lvl+1);
3122 /*-----------------------------------------------------------------*/
3123 /* geniCodeJumpTable - tries to create a jump table for switch */
3124 /*-----------------------------------------------------------------*/
3126 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3128 int min = 0, max = 0, t, cnt = 0;
3135 if (!tree || !caseVals)
3138 /* the criteria for creating a jump table is */
3139 /* all integer numbers between the maximum & minimum must */
3140 /* be present , the maximum value should not exceed 255 */
3141 min = max = (int) floatFromVal (vch = caseVals);
3142 SNPRINTF (buffer, sizeof(buffer),
3144 tree->values.switchVals.swNum,
3146 addSet (&labels, newiTempLabel (buffer));
3148 /* if there is only one case value then no need */
3149 if (!(vch = vch->next))
3154 if (((t = (int) floatFromVal (vch)) - max) != 1)
3156 SNPRINTF (buffer, sizeof(buffer),
3158 tree->values.switchVals.swNum,
3160 addSet (&labels, newiTempLabel (buffer));
3166 /* if the number of case statements <= 2 then */
3167 /* it is not economical to create the jump table */
3168 /* since two compares are needed for boundary conditions */
3169 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3172 if (tree->values.switchVals.swDefault)
3174 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3178 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3182 falseLabel = newiTempLabel (buffer);
3184 /* so we can create a jumptable */
3185 /* first we rule out the boundary conditions */
3186 /* if only optimization says so */
3187 if (!optimize.noJTabBoundary)
3189 sym_link *cetype = getSpec (operandType (cond));
3190 /* no need to check the lower bound if
3191 the condition is unsigned & minimum value is zero */
3192 if (!(min == 0 && SPEC_USIGN (cetype)))
3194 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3195 ic = newiCodeCondition (boundary, falseLabel, NULL);
3199 /* now for upper bounds */
3200 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3201 ic = newiCodeCondition (boundary, falseLabel, NULL);
3205 /* if the min is not zero then we no make it zero */
3208 cond = geniCodeSubtract (cond, operandFromLit (min));
3209 setOperandType (cond, UCHARTYPE);
3212 /* now create the jumptable */
3213 ic = newiCode (JUMPTABLE, NULL, NULL);
3214 IC_JTCOND (ic) = cond;
3215 IC_JTLABELS (ic) = labels;
3220 /*-----------------------------------------------------------------*/
3221 /* geniCodeSwitch - changes a switch to a if statement */
3222 /*-----------------------------------------------------------------*/
3224 geniCodeSwitch (ast * tree,int lvl)
3227 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3228 value *caseVals = tree->values.switchVals.swVals;
3229 symbol *trueLabel, *falseLabel;
3231 /* if we can make this a jump table */
3232 if (geniCodeJumpTable (cond, caseVals, tree))
3233 goto jumpTable; /* no need for the comparison */
3235 /* for the cases defined do */
3239 operand *compare = geniCodeLogic (cond,
3240 operandFromValue (caseVals),
3243 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3244 tree->values.switchVals.swNum,
3245 (int) floatFromVal (caseVals));
3246 trueLabel = newiTempLabel (buffer);
3248 ic = newiCodeCondition (compare, trueLabel, NULL);
3250 caseVals = caseVals->next;
3255 /* if default is present then goto break else break */
3256 if (tree->values.switchVals.swDefault)
3258 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3262 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3265 falseLabel = newiTempLabel (buffer);
3266 geniCodeGoto (falseLabel);
3269 ast2iCode (tree->right,lvl+1);
3272 /*-----------------------------------------------------------------*/
3273 /* geniCodeInline - intermediate code for inline assembler */
3274 /*-----------------------------------------------------------------*/
3276 geniCodeInline (ast * tree)
3280 ic = newiCode (INLINEASM, NULL, NULL);
3281 IC_INLINE (ic) = tree->values.inlineasm;
3285 /*-----------------------------------------------------------------*/
3286 /* geniCodeArrayInit - intermediate code for array initializer */
3287 /*-----------------------------------------------------------------*/
3289 geniCodeArrayInit (ast * tree, operand *array)
3293 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3294 ic = newiCode (ARRAYINIT, array, NULL);
3295 IC_ARRAYILIST (ic) = tree->values.constlist;
3297 operand *left=newOperand(), *right=newOperand();
3298 left->type=right->type=SYMBOL;
3299 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3300 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3301 ic = newiCode (ARRAYINIT, left, right);
3306 /*-----------------------------------------------------------------*/
3307 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3308 /* particular case. Ie : assigning or dereferencing array or ptr */
3309 /*-----------------------------------------------------------------*/
3310 set * lvaluereqSet = NULL;
3311 typedef struct lvalItem
3318 /*-----------------------------------------------------------------*/
3319 /* addLvaluereq - add a flag for lvalreq for current ast level */
3320 /*-----------------------------------------------------------------*/
3321 void addLvaluereq(int lvl)
3323 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3326 addSetHead(&lvaluereqSet,lpItem);
3329 /*-----------------------------------------------------------------*/
3330 /* delLvaluereq - del a flag for lvalreq for current ast level */
3331 /*-----------------------------------------------------------------*/
3335 lpItem = getSet(&lvaluereqSet);
3336 if(lpItem) Safe_free(lpItem);
3338 /*-----------------------------------------------------------------*/
3339 /* clearLvaluereq - clear lvalreq flag */
3340 /*-----------------------------------------------------------------*/
3341 void clearLvaluereq()
3344 lpItem = peekSet(lvaluereqSet);
3345 if(lpItem) lpItem->req = 0;
3347 /*-----------------------------------------------------------------*/
3348 /* getLvaluereq - get the last lvalreq level */
3349 /*-----------------------------------------------------------------*/
3350 int getLvaluereqLvl()
3353 lpItem = peekSet(lvaluereqSet);
3354 if(lpItem) return lpItem->lvl;
3357 /*-----------------------------------------------------------------*/
3358 /* isLvaluereq - is lvalreq valid for this level ? */
3359 /*-----------------------------------------------------------------*/
3360 int isLvaluereq(int lvl)
3363 lpItem = peekSet(lvaluereqSet);
3364 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3368 /*-----------------------------------------------------------------*/
3369 /* ast2iCode - creates an icodeList from an ast */
3370 /*-----------------------------------------------------------------*/
3372 ast2iCode (ast * tree,int lvl)
3374 operand *left = NULL;
3375 operand *right = NULL;
3379 /* set the global variables for filename & line number */
3381 filename = tree->filename;
3383 lineno = tree->lineno;
3385 block = tree->block;
3387 scopeLevel = tree->level;
3389 if (tree->type == EX_VALUE)
3390 return operandFromValue (tree->opval.val);
3392 if (tree->type == EX_LINK)
3393 return operandFromLink (tree->opval.lnk);
3395 /* if we find a nullop */
3396 if (tree->type == EX_OP &&
3397 (tree->opval.op == NULLOP ||
3398 tree->opval.op == BLOCK))
3400 ast2iCode (tree->left,lvl+1);
3401 ast2iCode (tree->right,lvl+1);
3405 /* special cases for not evaluating */
3406 if (tree->opval.op != ':' &&
3407 tree->opval.op != '?' &&
3408 tree->opval.op != CALL &&
3409 tree->opval.op != IFX &&
3410 tree->opval.op != LABEL &&
3411 tree->opval.op != GOTO &&
3412 tree->opval.op != SWITCH &&
3413 tree->opval.op != FUNCTION &&
3414 tree->opval.op != INLINEASM)
3417 if (IS_ASSIGN_OP (tree->opval.op) ||
3418 IS_DEREF_OP (tree) ||
3419 (tree->opval.op == '&' && !tree->right) ||
3420 tree->opval.op == PTR_OP)
3423 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3424 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3427 left = operandFromAst (tree->left,lvl);
3429 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3430 left = geniCodeRValue (left, TRUE);
3434 left = operandFromAst (tree->left,lvl);
3436 if (tree->opval.op == INC_OP ||
3437 tree->opval.op == DEC_OP)
3440 right = operandFromAst (tree->right,lvl);
3445 right = operandFromAst (tree->right,lvl);
3449 /* now depending on the type of operand */
3450 /* this will be a biggy */
3451 switch (tree->opval.op)
3454 case '[': /* array operation */
3456 //sym_link *ltype = operandType (left);
3457 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3458 left = geniCodeRValue (left, FALSE);
3459 right = geniCodeRValue (right, TRUE);
3462 return geniCodeArray (left, right,lvl);
3464 case '.': /* structure dereference */
3465 if (IS_PTR (operandType (left)))
3466 left = geniCodeRValue (left, TRUE);
3468 left = geniCodeRValue (left, FALSE);
3470 return geniCodeStruct (left, right, tree->lvalue);
3472 case PTR_OP: /* structure pointer dereference */
3475 pType = operandType (left);
3476 left = geniCodeRValue (left, TRUE);
3478 setOClass (pType, getSpec (operandType (left)));
3481 return geniCodeStruct (left, right, tree->lvalue);
3483 case INC_OP: /* increment operator */
3485 return geniCodePostInc (left);
3487 return geniCodePreInc (right);
3489 case DEC_OP: /* decrement operator */
3491 return geniCodePostDec (left);
3493 return geniCodePreDec (right);
3495 case '&': /* bitwise and or address of operator */
3497 { /* this is a bitwise operator */
3498 left = geniCodeRValue (left, FALSE);
3499 right = geniCodeRValue (right, FALSE);
3500 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3503 return geniCodeAddressOf (left);
3505 case '|': /* bitwise or & xor */
3507 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3508 geniCodeRValue (right, FALSE),
3513 return geniCodeDivision (geniCodeRValue (left, FALSE),
3514 geniCodeRValue (right, FALSE));
3517 return geniCodeModulus (geniCodeRValue (left, FALSE),
3518 geniCodeRValue (right, FALSE));
3521 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3522 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3524 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3528 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3529 geniCodeRValue (right, FALSE));
3531 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3535 return geniCodeAdd (geniCodeRValue (left, FALSE),
3536 geniCodeRValue (right, FALSE),lvl);
3538 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3541 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3542 geniCodeRValue (right, FALSE));
3545 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3546 geniCodeRValue (right, FALSE));
3548 #if 0 // this indeed needs a second thought
3552 // let's keep this simple: get the rvalue we need
3553 op=geniCodeRValue (right, FALSE);
3554 // now cast it to whatever we want
3555 op=geniCodeCast (operandType(left), op, FALSE);
3556 // if this is going to be used as an lvalue, make it so
3562 #else // bug #604575, is it a bug ????
3563 return geniCodeCast (operandType (left),
3564 geniCodeRValue (right, FALSE), FALSE);
3571 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3575 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3576 setOperandType (op, UCHARTYPE);
3587 return geniCodeLogic (geniCodeRValue (left, FALSE),
3588 geniCodeRValue (right, FALSE),
3591 return geniCodeConditional (tree,lvl);
3594 return operandFromLit (getSize (tree->right->ftype));
3598 sym_link *rtype = operandType (right);
3599 sym_link *ltype = operandType (left);
3600 if (IS_PTR (rtype) && IS_ITEMP (right)
3601 && right->isaddr && compareType (rtype->next, ltype) == 1)
3602 right = geniCodeRValue (right, TRUE);
3604 right = geniCodeRValue (right, FALSE);
3606 geniCodeAssign (left, right, 0);
3611 geniCodeAssign (left,
3612 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3614 geniCodeRValue (right, FALSE),FALSE), 0);
3618 geniCodeAssign (left,
3619 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3621 geniCodeRValue (right, FALSE)), 0);
3624 geniCodeAssign (left,
3625 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3627 geniCodeRValue (right, FALSE)), 0);
3630 sym_link *rtype = operandType (right);
3631 sym_link *ltype = operandType (left);
3632 if (IS_PTR (rtype) && IS_ITEMP (right)
3633 && right->isaddr && compareType (rtype->next, ltype) == 1)
3634 right = geniCodeRValue (right, TRUE);
3636 right = geniCodeRValue (right, FALSE);
3639 return geniCodeAssign (left,
3640 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3646 sym_link *rtype = operandType (right);
3647 sym_link *ltype = operandType (left);
3648 if (IS_PTR (rtype) && IS_ITEMP (right)
3649 && right->isaddr && compareType (rtype->next, ltype) == 1)
3651 right = geniCodeRValue (right, TRUE);
3655 right = geniCodeRValue (right, FALSE);
3658 geniCodeAssign (left,
3659 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3665 geniCodeAssign (left,
3666 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3668 geniCodeRValue (right, FALSE)), 0);
3671 geniCodeAssign (left,
3672 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3674 geniCodeRValue (right, FALSE)), 0);
3677 geniCodeAssign (left,
3678 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3680 geniCodeRValue (right, FALSE),
3682 operandType (left)), 0);
3685 geniCodeAssign (left,
3686 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3688 geniCodeRValue (right, FALSE),
3690 operandType (left)), 0);
3693 geniCodeAssign (left,
3694 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3696 geniCodeRValue (right, FALSE),
3698 operandType (left)), 0);
3700 return geniCodeRValue (right, FALSE);
3703 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3706 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3707 return ast2iCode (tree->right,lvl+1);
3710 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3711 return ast2iCode (tree->right,lvl+1);
3714 geniCodeFunctionBody (tree,lvl);
3718 geniCodeReturn (right);
3722 geniCodeIfx (tree,lvl);
3726 geniCodeSwitch (tree,lvl);
3730 geniCodeInline (tree);
3734 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3741 /*-----------------------------------------------------------------*/
3742 /* reverseICChain - gets from the list and creates a linkedlist */
3743 /*-----------------------------------------------------------------*/
3750 while ((loop = getSet (&iCodeChain)))
3762 /*-----------------------------------------------------------------*/
3763 /* iCodeFromAst - given an ast will convert it to iCode */
3764 /*-----------------------------------------------------------------*/
3766 iCodeFromAst (ast * tree)
3768 returnLabel = newiTempLabel ("_return");
3769 entryLabel = newiTempLabel ("_entry");
3771 return reverseiCChain ();
3774 static const char *opTypeToStr(OPTYPE op)
3778 case SYMBOL: return "symbol";
3779 case VALUE: return "value";
3780 case TYPE: return "type";
3782 return "undefined type";
3786 operand *validateOpType(operand *op,
3793 if (op && op->type == type)
3798 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3799 " expected %s, got %s\n",
3800 macro, args, file, line,
3801 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3803 return op; // never reached, makes compiler happy.