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;
43 symbol *returnLabel; /* function return label */
44 symbol *entryLabel; /* function entry label */
46 /*-----------------------------------------------------------------*/
47 /* forward definition of some functions */
48 operand *geniCodeAssign (operand *, operand *, int, int);
49 static operand *geniCodeArray (operand *, operand *,int);
50 static operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
54 void setOClass (sym_link * ptr, sym_link * spec);
55 static operand *geniCodeCast (sym_link *, operand *, bool);
57 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
58 /* forward definition of ic print functions */
59 PRINTFUNC (picGetValueAtAddr);
60 PRINTFUNC (picSetValueAtAddr);
61 PRINTFUNC (picAddrOf);
62 PRINTFUNC (picGeneric);
63 PRINTFUNC (picGenericOne);
65 PRINTFUNC (picAssign);
69 PRINTFUNC (picJumpTable);
70 PRINTFUNC (picInline);
71 PRINTFUNC (picReceive);
72 PRINTFUNC (picDummyRead);
73 PRINTFUNC (picCritical);
74 PRINTFUNC (picEndCritical);
76 iCodeTable codeTable[] =
78 {'!', "not", picGenericOne, NULL},
79 {'~', "~", picGenericOne, NULL},
80 {RRC, "rrc", picGenericOne, NULL},
81 {RLC, "rlc", picGenericOne, NULL},
82 {GETHBIT, "ghbit", picGenericOne, NULL},
83 {UNARYMINUS, "-", picGenericOne, NULL},
84 {IPUSH, "push", picGenericOne, NULL},
85 {IPOP, "pop", picGenericOne, NULL},
86 {CALL, "call", picGenericOne, NULL},
87 {PCALL, "pcall", picGenericOne, NULL},
88 {FUNCTION, "proc", picGenericOne, NULL},
89 {ENDFUNCTION, "eproc", picGenericOne, NULL},
90 {RETURN, "ret", picGenericOne, NULL},
91 {'+', "+", picGeneric, NULL},
92 {'-', "-", picGeneric, NULL},
93 {'*', "*", picGeneric, NULL},
94 {'/', "/", picGeneric, NULL},
95 {'%', "%", picGeneric, NULL},
96 {'>', ">", picGeneric, NULL},
97 {'<', "<", picGeneric, NULL},
98 {LE_OP, "<=", picGeneric, NULL},
99 {GE_OP, ">=", picGeneric, NULL},
100 {EQ_OP, "==", picGeneric, NULL},
101 {NE_OP, "!=", picGeneric, NULL},
102 {AND_OP, "&&", picGeneric, NULL},
103 {OR_OP, "||", picGeneric, NULL},
104 {'^', "^", picGeneric, NULL},
105 {'|', "|", picGeneric, NULL},
106 {BITWISEAND, "&", picGeneric, NULL},
107 {LEFT_OP, "<<", picGeneric, NULL},
108 {RIGHT_OP, ">>", picGeneric, NULL},
109 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
110 {ADDRESS_OF, "&", picAddrOf, NULL},
111 {CAST, "<>", picCast, NULL},
112 {'=', ":=", picAssign, NULL},
113 {LABEL, "", picLabel, NULL},
114 {GOTO, "", picGoto, NULL},
115 {JUMPTABLE, "jtab", picJumpTable, NULL},
116 {IFX, "if", picIfx, NULL},
117 {INLINEASM, "", picInline, NULL},
118 {RECEIVE, "recv", picReceive, NULL},
119 {SEND, "send", picGenericOne, NULL},
120 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
121 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
122 {CRITICAL, "critical_start", picCritical, NULL},
123 {ENDCRITICAL, "critical_end", picEndCritical, NULL}
126 /*-----------------------------------------------------------------*/
127 /* checkConstantRange: check a constant against the type */
128 /*-----------------------------------------------------------------*/
131 /* pedantic=0: allmost anything is allowed as long as the absolute
132 value is within the bit range of the type, and -1 is treated as
133 0xf..f for unsigned types (e.g. in assign)
134 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
135 pedantic>1: "char c=200" is not allowed (evaluates to -56)
138 void checkConstantRange(sym_link *ltype, value *val, char *msg,
145 max = pow ((double)2.0, (double)bitsForType(ltype));
147 if (IS_LONG(val->type)) {
148 if (IS_UNSIGNED(val->type)) {
149 v=SPEC_CVAL(val->type).v_ulong;
151 v=SPEC_CVAL(val->type).v_long;
154 if (IS_UNSIGNED(val->type)) {
155 v=SPEC_CVAL(val->type).v_uint;
157 v=SPEC_CVAL(val->type).v_int;
163 // this could be a good idea
164 if (options.pedantic)
168 if (IS_FLOAT(ltype)) {
173 if (!IS_UNSIGNED(val->type) && v<0) {
175 if (IS_UNSIGNED(ltype) && (pedantic>1)) {
181 // if very pedantic: "char c=200" is not allowed
182 if (pedantic>1 && !IS_UNSIGNED(ltype)) {
183 max = max/2 + negative;
190 #if 0 // temporary disabled, leaving the warning as a reminder
192 SNPRINTF (message, sizeof(message), "for %s %s in %s",
193 IS_UNSIGNED(ltype) ? "unsigned" : "signed",
194 nounName(ltype), msg);
195 werror (W_CONST_RANGE, message);
203 /*-----------------------------------------------------------------*/
204 /* operandName - returns the name of the operand */
205 /*-----------------------------------------------------------------*/
207 printOperand (operand * op, FILE * file)
224 opetype = getSpec (operandType (op));
225 if (IS_FLOAT (opetype))
226 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
228 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
229 printTypeChain (operandType (op), file);
236 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}" , */
237 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
239 OP_LIVEFROM (op), OP_LIVETO (op),
240 OP_SYMBOL (op)->stack,
241 op->isaddr, OP_SYMBOL (op)->isreqv,
242 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
243 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
247 printTypeChain (operandType (op), file);
248 if (SPIL_LOC (op) && IS_ITEMP (op))
249 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
254 /* if assigned to registers */
255 if (OP_SYMBOL (op)->nRegs)
257 if (OP_SYMBOL (op)->isspilt)
259 if (!OP_SYMBOL (op)->remat)
260 if (OP_SYMBOL (op)->usl.spillLoc)
261 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
262 OP_SYMBOL (op)->usl.spillLoc->rname :
263 OP_SYMBOL (op)->usl.spillLoc->name));
265 fprintf (file, "[err]");
267 fprintf (file, "[remat]");
273 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
274 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
279 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
280 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
281 /* if assigned to registers */
282 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
286 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
287 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
288 OP_SYMBOL (op)->regs[i]->name :
297 printTypeChain (op->operand.typeOperand, file);
303 fprintf (file, "\n");
308 /*-----------------------------------------------------------------*/
309 /* print functions */
310 /*-----------------------------------------------------------------*/
311 PRINTFUNC (picGetValueAtAddr)
314 printOperand (IC_RESULT (ic), of);
317 printOperand (IC_LEFT (ic), of);
323 PRINTFUNC (picSetValueAtAddr)
327 printOperand (IC_LEFT (ic), of);
328 fprintf (of, "] = ");
329 printOperand (IC_RIGHT (ic), of);
333 PRINTFUNC (picAddrOf)
336 printOperand (IC_RESULT (ic), of);
337 if (IS_ITEMP (IC_LEFT (ic)))
340 fprintf (of, " = &[");
341 printOperand (IC_LEFT (ic), of);
344 if (IS_ITEMP (IC_LEFT (ic)))
345 fprintf (of, " offsetAdd ");
348 printOperand (IC_RIGHT (ic), of);
350 if (IS_ITEMP (IC_LEFT (ic)))
356 PRINTFUNC (picJumpTable)
361 fprintf (of, "%s\t", s);
362 printOperand (IC_JTCOND (ic), of);
364 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
365 sym = setNextItem (IC_JTLABELS (ic)))
366 fprintf (of, "\t\t\t%s\n", sym->name);
369 PRINTFUNC (picGeneric)
372 printOperand (IC_RESULT (ic), of);
374 printOperand (IC_LEFT (ic), of);
375 fprintf (of, " %s ", s);
376 printOperand (IC_RIGHT (ic), of);
380 PRINTFUNC (picGenericOne)
385 printOperand (IC_RESULT (ic), of);
391 fprintf (of, "%s ", s);
392 printOperand (IC_LEFT (ic), of);
395 if (!IC_RESULT (ic) && !IC_LEFT (ic))
398 if (ic->op == SEND || ic->op == RECEIVE) {
399 fprintf(of,"{argreg = %d}",ic->argreg);
407 printOperand (IC_RESULT (ic), of);
409 printOperand (IC_LEFT (ic), of);
410 printOperand (IC_RIGHT (ic), of);
415 PRINTFUNC (picAssign)
419 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
422 printOperand (IC_RESULT (ic), of);
424 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
427 fprintf (of, " %s ", s);
428 printOperand (IC_RIGHT (ic), of);
435 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
441 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
448 printOperand (IC_COND (ic), of);
451 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
454 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
456 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
460 PRINTFUNC (picInline)
462 fprintf (of, "%s", IC_INLINE (ic));
465 PRINTFUNC (picReceive)
467 printOperand (IC_RESULT (ic), of);
468 fprintf (of, " = %s ", s);
469 printOperand (IC_LEFT (ic), of);
473 PRINTFUNC (picDummyRead)
476 fprintf (of, "%s ", s);
477 printOperand (IC_RIGHT (ic), of);
481 PRINTFUNC (picCritical)
485 printOperand (IC_RESULT (ic), of);
487 fprintf (of, "(stack)");
488 fprintf (of, " = %s ", s);
492 PRINTFUNC (picEndCritical)
495 fprintf (of, "%s = ", s);
497 printOperand (IC_RIGHT (ic), of);
499 fprintf (of, "(stack)");
503 /*-----------------------------------------------------------------*/
504 /* piCode - prints one iCode */
505 /*-----------------------------------------------------------------*/
507 piCode (void *item, FILE * of)
515 icTab = getTableEntry (ic->op);
516 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
517 ic->filename, ic->lineno,
518 ic->seq, ic->key, ic->depth, ic->supportRtn);
519 icTab->iCodePrint (of, ic, icTab->printName);
525 printiCChain(ic,stdout);
527 /*-----------------------------------------------------------------*/
528 /* printiCChain - prints intermediate code for humans */
529 /*-----------------------------------------------------------------*/
531 printiCChain (iCode * icChain, FILE * of)
538 for (loop = icChain; loop; loop = loop->next)
540 if ((icTab = getTableEntry (loop->op)))
542 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
543 loop->filename, loop->lineno,
544 loop->seq, loop->key, loop->depth, loop->supportRtn);
546 icTab->iCodePrint (of, loop, icTab->printName);
552 /*-----------------------------------------------------------------*/
553 /* newOperand - allocate, init & return a new iCode */
554 /*-----------------------------------------------------------------*/
560 op = Safe_alloc ( sizeof (operand));
566 /*-----------------------------------------------------------------*/
567 /* newiCode - create and return a new iCode entry initialised */
568 /*-----------------------------------------------------------------*/
570 newiCode (int op, operand * left, operand * right)
574 ic = Safe_alloc ( sizeof (iCode));
576 ic->seqPoint = seqPoint;
578 ic->filename = filename;
580 ic->level = scopeLevel;
582 ic->key = iCodeKey++;
584 IC_RIGHT (ic) = right;
589 /*-----------------------------------------------------------------*/
590 /* newiCode for conditional statements */
591 /*-----------------------------------------------------------------*/
593 newiCodeCondition (operand * condition,
599 if (IS_VOID(operandType(condition))) {
600 werror(E_VOID_VALUE_USED);
603 ic = newiCode (IFX, NULL, NULL);
604 IC_COND (ic) = condition;
605 IC_TRUE (ic) = trueLabel;
606 IC_FALSE (ic) = falseLabel;
610 /*-----------------------------------------------------------------*/
611 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
612 /*-----------------------------------------------------------------*/
614 newiCodeLabelGoto (int op, symbol * label)
618 ic = newiCode (op, NULL, NULL);
622 IC_RIGHT (ic) = NULL;
623 IC_RESULT (ic) = NULL;
627 /*-----------------------------------------------------------------*/
628 /* newiTemp - allocate & return a newItemp Variable */
629 /*-----------------------------------------------------------------*/
637 SNPRINTF (buffer, sizeof(buffer), "%s", s);
641 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
644 itmp = newSymbol (buffer, 1);
645 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
651 /*-----------------------------------------------------------------*/
652 /* newiTempLabel - creates a temp variable label */
653 /*-----------------------------------------------------------------*/
655 newiTempLabel (char *s)
659 /* check if this alredy exists */
660 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
665 itmplbl = newSymbol (s, 1);
669 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
670 itmplbl = newSymbol (buffer, 1);
675 itmplbl->key = labelKey++;
676 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
680 /*-----------------------------------------------------------------*/
681 /* newiTempPreheaderLabel - creates a new preheader label */
682 /*-----------------------------------------------------------------*/
684 newiTempPreheaderLabel ()
688 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
689 itmplbl = newSymbol (buffer, 1);
693 itmplbl->key = labelKey++;
694 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
699 /*-----------------------------------------------------------------*/
700 /* initiCode - initialises some iCode related stuff */
701 /*-----------------------------------------------------------------*/
708 /*-----------------------------------------------------------------*/
709 /* copyiCode - make a copy of the iCode given */
710 /*-----------------------------------------------------------------*/
712 copyiCode (iCode * ic)
714 iCode *nic = newiCode (ic->op, NULL, NULL);
716 nic->lineno = ic->lineno;
717 nic->filename = ic->filename;
718 nic->block = ic->block;
719 nic->level = ic->level;
720 nic->parmBytes = ic->parmBytes;
722 /* deal with the special cases first */
726 IC_COND (nic) = operandFromOperand (IC_COND (ic));
727 IC_TRUE (nic) = IC_TRUE (ic);
728 IC_FALSE (nic) = IC_FALSE (ic);
732 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
733 IC_JTLABELS (nic) = IC_JTLABELS (ic);
738 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
739 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
743 IC_INLINE (nic) = IC_INLINE (ic);
747 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
751 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
752 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
753 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
759 /*-----------------------------------------------------------------*/
760 /* getTableEntry - gets the table entry for the given operator */
761 /*-----------------------------------------------------------------*/
763 getTableEntry (int oper)
767 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
768 if (oper == codeTable[i].icode)
769 return &codeTable[i];
774 /*-----------------------------------------------------------------*/
775 /* newiTempOperand - new intermediate temp operand */
776 /*-----------------------------------------------------------------*/
778 newiTempOperand (sym_link * type, char throwType)
781 operand *op = newOperand ();
785 itmp = newiTemp (NULL);
787 etype = getSpec (type);
789 if (IS_LITERAL (etype))
792 /* copy the type information */
794 itmp->etype = getSpec (itmp->type = (throwType ? type :
795 copyLinkChain (type)));
796 if (IS_LITERAL (itmp->etype))
798 SPEC_SCLS (itmp->etype) = S_REGISTER;
799 SPEC_OCLS (itmp->etype) = reg;
802 op->operand.symOperand = itmp;
803 op->key = itmp->key = ++operandKey;
807 /*-----------------------------------------------------------------*/
808 /* operandType - returns the type chain for an operand */
809 /*-----------------------------------------------------------------*/
811 operandType (operand * op)
813 /* depending on type of operand */
818 return op->operand.valOperand->type;
821 return op->operand.symOperand->type;
824 return op->operand.typeOperand;
826 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
827 " operand type not known ");
828 assert (0); /* should never come here */
829 /* Just to keep the compiler happy */
830 return (sym_link *) 0;
834 /*-----------------------------------------------------------------*/
835 /* isParamterToCall - will return 1 if op is a parameter to args */
836 /*-----------------------------------------------------------------*/
838 isParameterToCall (value * args, operand * op)
842 wassert (IS_SYMOP(op));
847 isSymbolEqual (op->operand.symOperand, tval->sym))
854 /*-----------------------------------------------------------------*/
855 /* isOperandGlobal - return 1 if operand is a global variable */
856 /*-----------------------------------------------------------------*/
858 isOperandGlobal (operand * op)
867 (op->operand.symOperand->level == 0 ||
868 IS_STATIC (op->operand.symOperand->etype) ||
869 IS_EXTERN (op->operand.symOperand->etype))
876 /*-----------------------------------------------------------------*/
877 /* isOperandVolatile - return 1 if the operand is volatile */
878 /*-----------------------------------------------------------------*/
880 isOperandVolatile (operand * op, bool chkTemp)
885 if (IS_ITEMP (op) && !chkTemp)
888 opetype = getSpec (optype = operandType (op));
890 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
893 if (IS_VOLATILE (opetype))
898 /*-----------------------------------------------------------------*/
899 /* isOperandLiteral - returns 1 if an operand contains a literal */
900 /*-----------------------------------------------------------------*/
902 isOperandLiteral (operand * op)
909 opetype = getSpec (operandType (op));
911 if (IS_LITERAL (opetype))
917 /*-----------------------------------------------------------------*/
918 /* isOperandInFarSpace - will return true if operand is in farSpace */
919 /*-----------------------------------------------------------------*/
921 isOperandInFarSpace (operand * op)
931 if (!IS_TRUE_SYMOP (op))
934 etype = SPIL_LOC (op)->etype;
940 etype = getSpec (operandType (op));
942 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
945 /*------------------------------------------------------------------*/
946 /* isOperandInDirSpace - will return true if operand is in dirSpace */
947 /*------------------------------------------------------------------*/
949 isOperandInDirSpace (operand * op)
959 if (!IS_TRUE_SYMOP (op))
962 etype = SPIL_LOC (op)->etype;
968 etype = getSpec (operandType (op));
970 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
973 /*--------------------------------------------------------------------*/
974 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
975 /*--------------------------------------------------------------------*/
977 isOperandInCodeSpace (operand * op)
987 etype = getSpec (operandType (op));
989 if (!IS_TRUE_SYMOP (op))
992 etype = SPIL_LOC (op)->etype;
998 etype = getSpec (operandType (op));
1000 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1003 /*-----------------------------------------------------------------*/
1004 /* isOperandOnStack - will return true if operand is on stack */
1005 /*-----------------------------------------------------------------*/
1007 isOperandOnStack (operand * op)
1017 etype = getSpec (operandType (op));
1018 if (IN_STACK (etype) ||
1019 OP_SYMBOL(op)->onStack ||
1020 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1026 /*-----------------------------------------------------------------*/
1027 /* isOclsExpensive - will return true if accesses to an output */
1028 /* storage class are expensive */
1029 /*-----------------------------------------------------------------*/
1031 isOclsExpensive (struct memmap *oclass)
1033 if (port->oclsExpense)
1034 return port->oclsExpense (oclass) > 0;
1036 /* In the absence of port specific guidance, assume only */
1037 /* farspace is expensive. */
1038 return IN_FARSPACE (oclass);
1041 /*-----------------------------------------------------------------*/
1042 /* operandLitValue - literal value of an operand */
1043 /*-----------------------------------------------------------------*/
1045 operandLitValue (operand * op)
1047 assert (isOperandLiteral (op));
1049 return floatFromVal (op->operand.valOperand);
1052 /*-----------------------------------------------------------------*/
1053 /* getBuiltInParms - returns parameters to a builtin functions */
1054 /*-----------------------------------------------------------------*/
1055 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1060 /* builtin functions uses only SEND for parameters */
1061 while (ic->op != CALL) {
1062 assert(ic->op == SEND && ic->builtinSEND);
1063 ic->generated = 1; /* mark the icode as generated */
1064 parms[*pcount] = IC_LEFT(ic);
1070 /* make sure this is a builtin function call */
1071 assert(IS_SYMOP(IC_LEFT(ic)));
1072 ftype = operandType(IC_LEFT(ic));
1073 assert(IFFUNC_ISBUILTIN(ftype));
1077 /*-----------------------------------------------------------------*/
1078 /* operandOperation - performs operations on operands */
1079 /*-----------------------------------------------------------------*/
1081 operandOperation (operand * left, operand * right,
1082 int op, sym_link * type)
1084 sym_link *let , *ret=NULL;
1085 operand *retval = (operand *) 0;
1087 assert (isOperandLiteral (left));
1088 let = getSpec(operandType(left));
1090 assert (isOperandLiteral (right));
1091 ret = getSpec(operandType(right));
1097 retval = operandFromValue (valCastLiteral (type,
1098 operandLitValue (left) +
1099 operandLitValue (right)));
1102 retval = operandFromValue (valCastLiteral (type,
1103 operandLitValue (left) -
1104 operandLitValue (right)));
1108 retval = operandFromValue (valCastLiteral (type,
1109 operandLitValue (left) *
1110 operandLitValue (right)));
1111 This could be all we've to do, but with gcc we've to take care about
1112 overflows. Two examples:
1113 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1114 significant bits are lost (52 in fraction, 63 bits would be
1115 necessary to keep full precision).
1116 If the resulting double value is greater than ULONG_MAX (resp.
1117 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1120 /* if it is not a specifier then we can assume that */
1121 /* it will be an unsigned long */
1122 if (IS_INT (type) ||
1125 /* long is handled here, because it can overflow with double */
1126 if (IS_LONG (type) ||
1128 /* signed and unsigned mul are the same, as long as the precision
1129 of the result isn't bigger than the precision of the operands. */
1130 retval = operandFromValue (valCastLiteral (type,
1131 (TYPE_UDWORD) operandLitValue (left) *
1132 (TYPE_UDWORD) operandLitValue (right)));
1133 else if (IS_UNSIGNED (type)) /* unsigned int */
1135 /* unsigned int is handled here in order to detect overflow */
1136 TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
1137 (TYPE_UWORD) operandLitValue (right);
1139 retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
1140 if (ul != (TYPE_UWORD) ul)
1143 else /* signed int */
1145 /* signed int is handled here in order to detect overflow */
1146 TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
1147 (TYPE_WORD) operandLitValue (right);
1149 retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
1150 if (l != (TYPE_WORD) l)
1155 /* all others go here: */
1156 retval = operandFromValue (valCastLiteral (type,
1157 operandLitValue (left) *
1158 operandLitValue (right)));
1161 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1163 werror (E_DIVIDE_BY_ZERO);
1169 if (IS_UNSIGNED (type))
1171 SPEC_USIGN (let) = 1;
1172 SPEC_USIGN (ret) = 1;
1173 retval = operandFromValue (valCastLiteral (type,
1174 (TYPE_UDWORD) operandLitValue (left) /
1175 (TYPE_UDWORD) operandLitValue (right)));
1179 retval = operandFromValue (valCastLiteral (type,
1180 operandLitValue (left) /
1181 operandLitValue (right)));
1186 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1188 werror (E_DIVIDE_BY_ZERO);
1193 if (IS_UNSIGNED (type))
1194 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1195 (TYPE_UDWORD) operandLitValue (right));
1197 retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1198 (TYPE_DWORD) operandLitValue (right));
1202 /* The number of left shifts is always unsigned. Signed doesn't make
1203 sense here. Shifting by a negative number is impossible. */
1204 retval = operandFromValue (valCastLiteral (type,
1205 ((TYPE_UDWORD) operandLitValue (left) <<
1206 (TYPE_UDWORD) operandLitValue (right))));
1209 /* The number of right shifts is always unsigned. Signed doesn't make
1210 sense here. Shifting by a negative number is impossible. */
1211 if (IS_UNSIGNED(let))
1212 /* unsigned: logic shift right */
1213 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1214 (TYPE_UDWORD) operandLitValue (right));
1216 /* signed: arithmetic shift right */
1217 retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1218 (TYPE_UDWORD) operandLitValue (right));
1221 if (IS_FLOAT (let) ||
1224 retval = operandFromLit (operandLitValue (left) ==
1225 operandLitValue (right));
1229 /* this op doesn't care about signedness */
1232 l = (TYPE_UDWORD) operandLitValue (left);
1233 r = (TYPE_UDWORD) operandLitValue (right);
1234 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1235 neccessary to strip them to 16 bit.
1236 Literals are reduced to their cheapest type, therefore left and
1237 right might have different types. It's neccessary to find a
1238 common type: int (used for char too) or long */
1239 if (!IS_LONG (let) &&
1245 retval = operandFromLit (l == r);
1249 retval = operandFromLit (operandLitValue (left) <
1250 operandLitValue (right));
1253 retval = operandFromLit (operandLitValue (left) <=
1254 operandLitValue (right));
1257 retval = operandFromLit (operandLitValue (left) !=
1258 operandLitValue (right));
1261 retval = operandFromLit (operandLitValue (left) >
1262 operandLitValue (right));
1265 retval = operandFromLit (operandLitValue (left) >=
1266 operandLitValue (right));
1269 retval = operandFromValue (valCastLiteral (type,
1270 (TYPE_UDWORD)operandLitValue(left) &
1271 (TYPE_UDWORD)operandLitValue(right)));
1274 retval = operandFromValue (valCastLiteral (type,
1275 (TYPE_UDWORD)operandLitValue(left) |
1276 (TYPE_UDWORD)operandLitValue(right)));
1279 retval = operandFromValue (valCastLiteral (type,
1280 (TYPE_UDWORD)operandLitValue(left) ^
1281 (TYPE_UDWORD)operandLitValue(right)));
1284 retval = operandFromLit (operandLitValue (left) &&
1285 operandLitValue (right));
1288 retval = operandFromLit (operandLitValue (left) ||
1289 operandLitValue (right));
1293 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1295 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1301 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1303 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1309 retval = operandFromValue (valCastLiteral (type,
1310 -1 * operandLitValue (left)));
1314 retval = operandFromValue (valCastLiteral (type,
1316 operandLitValue (left))));
1320 retval = operandFromLit (!operandLitValue (left));
1324 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1325 " operandOperation invalid operator ");
1333 /*-----------------------------------------------------------------*/
1334 /* isOperandEqual - compares two operand & return 1 if they r = */
1335 /*-----------------------------------------------------------------*/
1337 isOperandEqual (operand * left, operand * right)
1339 /* if the pointers are equal then they are equal */
1343 /* if either of them null then false */
1344 if (!left || !right)
1347 if (left->type != right->type)
1350 if (IS_SYMOP (left) && IS_SYMOP (right))
1351 return left->key == right->key;
1353 /* if types are the same */
1357 return isSymbolEqual (left->operand.symOperand,
1358 right->operand.symOperand);
1360 return (floatFromVal (left->operand.valOperand) ==
1361 floatFromVal (right->operand.valOperand));
1363 if (compareType (left->operand.typeOperand,
1364 right->operand.typeOperand) == 1)
1371 /*-------------------------------------------------------------------*/
1372 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1373 /*-------------------------------------------------------------------*/
1375 isiCodeEqual (iCode * left, iCode * right)
1377 /* if the same pointer */
1381 /* if either of them null */
1382 if (!left || !right)
1385 /* if operand are the same */
1386 if (left->op == right->op)
1389 /* compare all the elements depending on type */
1390 if (left->op != IFX)
1392 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1394 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1400 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1402 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1404 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1413 /*-----------------------------------------------------------------*/
1414 /* newiTempFromOp - create a temp Operand with same attributes */
1415 /*-----------------------------------------------------------------*/
1417 newiTempFromOp (operand * op)
1427 nop = newiTempOperand (operandType (op), TRUE);
1428 nop->isaddr = op->isaddr;
1429 nop->isvolatile = op->isvolatile;
1430 nop->isGlobal = op->isGlobal;
1431 nop->isLiteral = op->isLiteral;
1432 nop->usesDefs = op->usesDefs;
1433 nop->isParm = op->isParm;
1437 /*-----------------------------------------------------------------*/
1438 /* operand from operand - creates an operand holder for the type */
1439 /*-----------------------------------------------------------------*/
1441 operandFromOperand (operand * op)
1447 nop = newOperand ();
1448 nop->type = op->type;
1449 nop->isaddr = op->isaddr;
1451 nop->isvolatile = op->isvolatile;
1452 nop->isGlobal = op->isGlobal;
1453 nop->isLiteral = op->isLiteral;
1454 nop->usesDefs = op->usesDefs;
1455 nop->isParm = op->isParm;
1460 nop->operand.symOperand = op->operand.symOperand;
1463 nop->operand.valOperand = op->operand.valOperand;
1466 nop->operand.typeOperand = op->operand.typeOperand;
1473 /*-----------------------------------------------------------------*/
1474 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1475 /*-----------------------------------------------------------------*/
1477 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1479 operand *nop = operandFromOperand (op);
1481 if (nop->type == SYMBOL)
1483 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1484 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1490 /*-----------------------------------------------------------------*/
1491 /* operandFromSymbol - creates an operand from a symbol */
1492 /*-----------------------------------------------------------------*/
1494 operandFromSymbol (symbol * sym)
1499 /* if the symbol's type is a literal */
1500 /* then it is an enumerator type */
1501 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1502 return operandFromValue (valFromType (sym->etype));
1505 sym->key = ++operandKey;
1507 /* if this an implicit variable, means struct/union */
1508 /* member so just return it */
1509 if (sym->implicit || IS_FUNC (sym->type))
1513 op->operand.symOperand = sym;
1515 op->isvolatile = isOperandVolatile (op, TRUE);
1516 op->isGlobal = isOperandGlobal (op);
1520 /* under the following conditions create a
1521 register equivalent for a local symbol */
1522 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1523 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1525 (!(options.model == MODEL_FLAT24)) ) &&
1526 options.stackAuto == 0)
1529 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1530 !IS_FUNC (sym->type) && /* not a function */
1531 !sym->_isparm && /* not a parameter */
1532 IS_AUTO (sym) && /* is a local auto variable */
1533 !sym->addrtaken && /* whose address has not been taken */
1534 !sym->reqv && /* does not already have a reg equivalence */
1535 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1536 !sym->islbl && /* not a label */
1537 ok && /* farspace check */
1538 !IS_BITVAR (sym->etype) /* not a bit variable */
1542 /* we will use it after all optimizations
1543 and before liveRange calculation */
1544 sym->reqv = newiTempOperand (sym->type, 0);
1545 sym->reqv->key = sym->key;
1546 OP_SYMBOL (sym->reqv)->prereqv = sym;
1547 OP_SYMBOL (sym->reqv)->key = sym->key;
1548 OP_SYMBOL (sym->reqv)->isreqv = 1;
1549 OP_SYMBOL (sym->reqv)->islocal = 1;
1550 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1551 SPIL_LOC (sym->reqv) = sym;
1554 if (!IS_AGGREGATE (sym->type))
1558 op->operand.symOperand = sym;
1561 op->isvolatile = isOperandVolatile (op, TRUE);
1562 op->isGlobal = isOperandGlobal (op);
1563 op->isPtr = IS_PTR (operandType (op));
1564 op->isParm = sym->_isparm;
1569 /* itemp = &[_symbol] */
1571 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1572 IC_LEFT (ic)->type = SYMBOL;
1573 IC_LEFT (ic)->operand.symOperand = sym;
1574 IC_LEFT (ic)->key = sym->key;
1575 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1576 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1577 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1580 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1581 if (IS_ARRAY (sym->type))
1583 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1584 IC_RESULT (ic)->isaddr = 0;
1587 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1591 return IC_RESULT (ic);
1594 /*-----------------------------------------------------------------*/
1595 /* operandFromValue - creates an operand from value */
1596 /*-----------------------------------------------------------------*/
1598 operandFromValue (value * val)
1602 /* if this is a symbol then do the symbol thing */
1604 return operandFromSymbol (val->sym);
1606 /* this is not a symbol */
1609 op->operand.valOperand = val;
1610 op->isLiteral = isOperandLiteral (op);
1614 /*-----------------------------------------------------------------*/
1615 /* operandFromLink - operand from typeChain */
1616 /*-----------------------------------------------------------------*/
1618 operandFromLink (sym_link * type)
1622 /* operand from sym_link */
1628 op->operand.typeOperand = copyLinkChain (type);
1632 /*-----------------------------------------------------------------*/
1633 /* operandFromLit - makes an operand from a literal value */
1634 /*-----------------------------------------------------------------*/
1636 operandFromLit (double i)
1638 return operandFromValue (valueFromLit (i));
1641 /*-----------------------------------------------------------------*/
1642 /* operandFromAst - creates an operand from an ast */
1643 /*-----------------------------------------------------------------*/
1645 operandFromAst (ast * tree,int lvl)
1651 /* depending on type do */
1655 return ast2iCode (tree,lvl+1);
1659 return operandFromValue (tree->opval.val);
1663 return operandFromLink (tree->opval.lnk);
1670 /* Just to keep the compiler happy */
1671 return (operand *) 0;
1674 /*-----------------------------------------------------------------*/
1675 /* setOperandType - sets the operand's type to the given type */
1676 /*-----------------------------------------------------------------*/
1678 setOperandType (operand * op, sym_link * type)
1680 /* depending on the type of operand */
1685 op->operand.valOperand->etype =
1686 getSpec (op->operand.valOperand->type =
1687 copyLinkChain (type));
1691 if (op->operand.symOperand->isitmp)
1692 op->operand.symOperand->etype =
1693 getSpec (op->operand.symOperand->type =
1694 copyLinkChain (type));
1696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697 "attempt to modify type of source");
1701 op->operand.typeOperand = copyLinkChain (type);
1707 /*-----------------------------------------------------------------*/
1708 /* Get size in byte of ptr need to access an array */
1709 /*-----------------------------------------------------------------*/
1711 getArraySizePtr (operand * op)
1713 sym_link *ltype = operandType(op);
1717 int size = getSize(ltype);
1718 return(IS_GENPTR(ltype)?(size-1):size);
1723 sym_link *letype = getSpec(ltype);
1724 switch (PTR_TYPE (SPEC_OCLS (letype)))
1736 return (GPTRSIZE-1);
1745 /*-----------------------------------------------------------------*/
1746 /* perform "usual unary conversions" */
1747 /*-----------------------------------------------------------------*/
1750 usualUnaryConversions (operand * op)
1752 if (IS_INTEGRAL (operandType (op)))
1754 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1757 return geniCodeCast (INTTYPE, op, TRUE);
1764 /*-----------------------------------------------------------------*/
1765 /* perform "usual binary conversions" */
1766 /*-----------------------------------------------------------------*/
1769 usualBinaryConversions (operand ** op1, operand ** op2,
1770 RESULT_TYPE resultType, int op)
1773 sym_link *rtype = operandType (*op2);
1774 sym_link *ltype = operandType (*op1);
1776 ctype = computeType (ltype, rtype, resultType, op);
1783 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1785 /* one byte operations: keep signedness for code generator */
1793 *op1 = geniCodeCast (ctype, *op1, TRUE);
1794 *op2 = geniCodeCast (ctype, *op2, TRUE);
1799 /*-----------------------------------------------------------------*/
1800 /* geniCodeValueAtAddress - generate intermeditate code for value */
1802 /*-----------------------------------------------------------------*/
1804 geniCodeRValue (operand * op, bool force)
1807 sym_link *type = operandType (op);
1808 sym_link *etype = getSpec (type);
1810 /* if this is an array & already */
1811 /* an address then return this */
1812 if (IS_AGGREGATE (type) ||
1813 (IS_PTR (type) && !force && !op->isaddr))
1814 return operandFromOperand (op);
1816 /* if this is not an address then must be */
1817 /* rvalue already so return this one */
1821 /* if this is not a temp symbol then */
1822 if (!IS_ITEMP (op) &&
1824 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1826 op = operandFromOperand (op);
1831 if (IS_SPEC (type) &&
1832 IS_TRUE_SYMOP (op) &&
1833 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1834 (options.model == MODEL_FLAT24) ))
1836 op = operandFromOperand (op);
1841 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1842 if (IS_PTR (type) && op->isaddr && force)
1845 type = copyLinkChain (type);
1847 IC_RESULT (ic) = newiTempOperand (type, 1);
1848 IC_RESULT (ic)->isaddr = 0;
1850 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1854 return IC_RESULT (ic);
1857 /*-----------------------------------------------------------------*/
1858 /* geniCodeCast - changes the value from one type to another */
1859 /*-----------------------------------------------------------------*/
1861 geniCodeCast (sym_link * type, operand * op, bool implicit)
1865 sym_link *opetype = getSpec (optype = operandType (op));
1869 /* one of them has size zero then error */
1870 if (IS_VOID (optype))
1872 werror (E_CAST_ZERO);
1876 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1878 geniCodeArray2Ptr (op);
1882 /* if the operand is already the desired type then do nothing */
1883 if (compareType (type, optype) == 1)
1886 /* if this is a literal then just change the type & return */
1887 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1889 return operandFromValue (valCastLiteral (type,
1890 operandLitValue (op)));
1893 /* if casting to/from pointers, do some checking */
1894 if (IS_PTR(type)) { // to a pointer
1895 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1896 if (IS_INTEGRAL(optype)) {
1897 // maybe this is NULL, than it's ok.
1898 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1899 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1900 // no way to set the storage
1901 if (IS_LITERAL(optype)) {
1902 werror(E_LITERAL_GENERIC);
1905 werror(E_NONPTR2_GENPTR);
1908 } else if (implicit) {
1909 werror(W_INTEGRAL2PTR_NOCAST);
1914 // shouldn't do that with float, array or structure unless to void
1915 if (!IS_VOID(getSpec(type)) &&
1916 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1917 werror(E_INCOMPAT_TYPES);
1921 } else { // from a pointer to a pointer
1922 if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
1923 // if not a pointer to a function
1924 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1925 if (implicit) { // if not to generic, they have to match
1926 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1927 werror(E_INCOMPAT_PTYPES);
1934 } else { // to a non pointer
1935 if (IS_PTR(optype)) { // from a pointer
1936 if (implicit) { // sneaky
1937 if (IS_INTEGRAL(type)) {
1938 werror(W_PTR2INTEGRAL_NOCAST);
1940 } else { // shouldn't do that with float, array or structure
1941 werror(E_INCOMPAT_TYPES);
1948 printFromToType (optype, type);
1951 /* if they are the same size create an assignment */
1953 /* This seems very dangerous to me, since there are several */
1954 /* optimizations (for example, gcse) that don't notice the */
1955 /* cast hidden in this assignement and may simplify an */
1956 /* iCode to use the original (uncasted) operand. */
1957 /* Unfortunately, other things break when this cast is */
1958 /* made explicit. Need to fix this someday. */
1959 /* -- EEP, 2004/01/21 */
1960 if (getSize (type) == getSize (optype) &&
1961 !IS_BITFIELD (type) &&
1963 !IS_FLOAT (optype) &&
1964 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1965 (!IS_SPEC (type) && !IS_SPEC (optype))))
1967 ic = newiCode ('=', NULL, op);
1968 IC_RESULT (ic) = newiTempOperand (type, 0);
1969 SPIL_LOC (IC_RESULT (ic)) =
1970 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1971 IC_RESULT (ic)->isaddr = 0;
1975 ic = newiCode (CAST, operandFromLink (type),
1976 geniCodeRValue (op, FALSE));
1978 IC_RESULT (ic) = newiTempOperand (type, 0);
1981 /* preserve the storage class & output class */
1982 /* of the original variable */
1983 restype = getSpec (operandType (IC_RESULT (ic)));
1984 if (!IS_LITERAL(opetype) &&
1986 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1987 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1990 return IC_RESULT (ic);
1993 /*-----------------------------------------------------------------*/
1994 /* geniCodeLabel - will create a Label */
1995 /*-----------------------------------------------------------------*/
1997 geniCodeLabel (symbol * label)
2001 ic = newiCodeLabelGoto (LABEL, label);
2005 /*-----------------------------------------------------------------*/
2006 /* geniCodeGoto - will create a Goto */
2007 /*-----------------------------------------------------------------*/
2009 geniCodeGoto (symbol * label)
2013 ic = newiCodeLabelGoto (GOTO, label);
2017 /*-----------------------------------------------------------------*/
2018 /* geniCodeMultiply - gen intermediate code for multiplication */
2019 /*-----------------------------------------------------------------*/
2021 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2028 /* if they are both literal then we know the result */
2029 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2030 return operandFromValue (valMult (left->operand.valOperand,
2031 right->operand.valOperand));
2033 if (IS_LITERAL(retype)) {
2034 p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2037 resType = usualBinaryConversions (&left, &right, resultType, '*');
2039 rtype = operandType (right);
2040 retype = getSpec (rtype);
2041 ltype = operandType (left);
2042 letype = getSpec (ltype);
2045 /* if the right is a literal & power of 2 */
2046 /* then make it a left shift */
2047 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2048 efficient in most cases than 2 bytes result = 2 bytes << literal
2049 if port has 1 byte muldiv */
2050 if (p2 && !IS_FLOAT (letype)
2051 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2052 && (port->support.muldiv == 1))
2053 && strcmp (port->target, "pic14") != 0 /* don't shift for pic */
2054 && strcmp (port->target, "pic16") != 0)
2056 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2058 /* LEFT_OP need same size for left and result, */
2059 left = geniCodeCast (resType, left, TRUE);
2060 ltype = operandType (left);
2062 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2066 ic = newiCode ('*', left, right); /* normal multiplication */
2067 /* if the size left or right > 1 then support routine */
2068 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2072 IC_RESULT (ic) = newiTempOperand (resType, 1);
2075 return IC_RESULT (ic);
2078 /*-----------------------------------------------------------------*/
2079 /* geniCodeDivision - gen intermediate code for division */
2080 /*-----------------------------------------------------------------*/
2082 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2087 sym_link *rtype = operandType (right);
2088 sym_link *retype = getSpec (rtype);
2089 sym_link *ltype = operandType (left);
2090 sym_link *letype = getSpec (ltype);
2092 resType = usualBinaryConversions (&left, &right, resultType, '/');
2094 /* if the right is a literal & power of 2
2095 and left is unsigned then make it a
2097 if (IS_LITERAL (retype) &&
2098 !IS_FLOAT (letype) &&
2099 IS_UNSIGNED(letype) &&
2100 (p2 = powof2 ((TYPE_UDWORD)
2101 floatFromVal (right->operand.valOperand)))) {
2102 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2106 ic = newiCode ('/', left, right); /* normal division */
2107 /* if the size left or right > 1 then support routine */
2108 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2111 IC_RESULT (ic) = newiTempOperand (resType, 0);
2114 return IC_RESULT (ic);
2116 /*-----------------------------------------------------------------*/
2117 /* geniCodeModulus - gen intermediate code for modulus */
2118 /*-----------------------------------------------------------------*/
2120 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2126 /* if they are both literal then we know the result */
2127 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2128 return operandFromValue (valMod (left->operand.valOperand,
2129 right->operand.valOperand));
2131 resType = usualBinaryConversions (&left, &right, resultType, '%');
2133 /* now they are the same size */
2134 ic = newiCode ('%', left, right);
2136 /* if the size left or right > 1 then support routine */
2137 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2139 IC_RESULT (ic) = newiTempOperand (resType, 0);
2142 return IC_RESULT (ic);
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2147 /*-----------------------------------------------------------------*/
2149 geniCodePtrPtrSubtract (operand * left, operand * right)
2155 /* if they are both literals then */
2156 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2158 result = operandFromValue (valMinus (left->operand.valOperand,
2159 right->operand.valOperand));
2163 ic = newiCode ('-', left, right);
2165 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2169 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2173 // should we really do this? is this ANSI?
2174 return geniCodeDivision (result,
2175 operandFromLit (getSize (ltype->next)),
2179 /*-----------------------------------------------------------------*/
2180 /* geniCodeSubtract - generates code for subtraction */
2181 /*-----------------------------------------------------------------*/
2183 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2190 /* if they both pointers then */
2191 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2192 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2193 return geniCodePtrPtrSubtract (left, right);
2195 /* if they are both literal then we know the result */
2196 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2197 && left->isLiteral && right->isLiteral)
2198 return operandFromValue (valMinus (left->operand.valOperand,
2199 right->operand.valOperand));
2201 /* if left is an array or pointer */
2202 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2204 isarray = left->isaddr;
2205 right = geniCodeMultiply (right,
2206 operandFromLit (getSize (ltype->next)),
2207 (getArraySizePtr(left) >= INTSIZE) ?
2210 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2213 { /* make them the same size */
2214 resType = usualBinaryConversions (&left, &right, resultType, '-');
2217 ic = newiCode ('-', left, right);
2219 IC_RESULT (ic) = newiTempOperand (resType, 1);
2220 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2222 /* if left or right is a float */
2223 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2227 return IC_RESULT (ic);
2230 /*-----------------------------------------------------------------*/
2231 /* geniCodeAdd - generates iCode for addition */
2232 /*-----------------------------------------------------------------*/
2234 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2243 /* if the right side is LITERAL zero */
2244 /* return the left side */
2245 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2248 /* if left is literal zero return right */
2249 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2252 /* if left is a pointer then size */
2253 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2255 isarray = left->isaddr;
2256 // there is no need to multiply with 1
2257 if (getSize (ltype->next) != 1)
2259 size = operandFromLit (getSize (ltype->next));
2260 SPEC_USIGN (getSpec (operandType (size))) = 1;
2261 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2262 right = geniCodeMultiply (right,
2264 (getArraySizePtr(left) >= INTSIZE) ?
2267 /* Even if right is a 'unsigned char',
2268 the result will be a 'signed int' due to the promotion rules.
2269 It doesn't make sense when accessing arrays, so let's fix it here: */
2271 SPEC_USIGN (getSpec (operandType (right))) = 1;
2273 resType = copyLinkChain (ltype);
2276 { // make them the same size
2277 resType = usualBinaryConversions (&left, &right, resultType, '+');
2280 /* if they are both literals then we know */
2281 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2282 && left->isLiteral && right->isLiteral)
2283 return operandFromValue (valPlus (valFromType (ltype),
2284 valFromType (rtype)));
2286 ic = newiCode ('+', left, right);
2288 IC_RESULT (ic) = newiTempOperand (resType, 1);
2289 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2291 /* if left or right is a float then support
2293 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2298 return IC_RESULT (ic);
2302 /*-----------------------------------------------------------------*/
2303 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2304 /*-----------------------------------------------------------------*/
2306 aggrToPtr (sym_link * type, bool force)
2311 if (IS_PTR (type) && !force)
2314 etype = getSpec (type);
2315 ptype = newLink (DECLARATOR);
2319 /* set the pointer depending on the storage class */
2320 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2324 /*------------------------------------------------------------------*/
2325 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2326 /*------------------------------------------------------------------*/
2328 aggrToPtrDclType (sym_link * type, bool force)
2330 if (IS_PTR (type) && !force)
2331 return DCL_TYPE (type);
2333 /* return the pointer depending on the storage class */
2334 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2337 /*-----------------------------------------------------------------*/
2338 /* geniCodeArray2Ptr - array to pointer */
2339 /*-----------------------------------------------------------------*/
2341 geniCodeArray2Ptr (operand * op)
2343 sym_link *optype = operandType (op);
2344 sym_link *opetype = getSpec (optype);
2346 /* set the pointer depending on the storage class */
2347 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2354 /*-----------------------------------------------------------------*/
2355 /* geniCodeArray - array access */
2356 /*-----------------------------------------------------------------*/
2358 geniCodeArray (operand * left, operand * right, int lvl)
2362 sym_link *ltype = operandType (left);
2367 if (IS_PTR (ltype->next) && left->isaddr)
2369 left = geniCodeRValue (left, FALSE);
2372 return geniCodeDerefPtr (geniCodeAdd (left,
2374 (getArraySizePtr(left) >= INTSIZE) ?
2380 size = operandFromLit (getSize (ltype->next));
2381 SPEC_USIGN (getSpec (operandType (size))) = 1;
2382 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2383 right = geniCodeMultiply (right,
2385 (getArraySizePtr(left) >= INTSIZE) ?
2388 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2389 It doesn't make sense when accessing arrays, so let's fix it here: */
2391 SPEC_USIGN (getSpec (operandType (right))) = 1;
2392 /* we can check for limits here */
2393 /* already done in SDCCast.c
2394 if (isOperandLiteral (right) &&
2397 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2399 werror (W_IDX_OUT_OF_BOUNDS,
2400 (int) operandLitValue (right) / getSize (ltype->next),
2405 ic = newiCode ('+', left, right);
2407 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2408 !IS_AGGREGATE (ltype->next) &&
2409 !IS_PTR (ltype->next))
2410 ? ltype : ltype->next), 0);
2412 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2415 return IC_RESULT (ic);
2418 /*-----------------------------------------------------------------*/
2419 /* geniCodeStruct - generates intermediate code for structures */
2420 /*-----------------------------------------------------------------*/
2422 geniCodeStruct (operand * left, operand * right, bool islval)
2425 sym_link *type = operandType (left);
2426 sym_link *etype = getSpec (type);
2428 symbol *element = getStructElement (SPEC_STRUCT (etype),
2429 right->operand.symOperand);
2431 wassert(IS_SYMOP(right));
2433 /* add the offset */
2434 ic = newiCode ('+', left, operandFromLit (element->offset));
2436 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2438 /* preserve the storage & output class of the struct */
2439 /* as well as the volatile attribute */
2440 retype = getSpec (operandType (IC_RESULT (ic)));
2441 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2442 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2443 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2444 SPEC_CONST (retype) |= SPEC_CONST (etype);
2446 if (IS_PTR (element->type))
2447 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2449 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2452 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2455 /*-----------------------------------------------------------------*/
2456 /* geniCodePostInc - generate int code for Post increment */
2457 /*-----------------------------------------------------------------*/
2459 geniCodePostInc (operand * op)
2463 sym_link *optype = operandType (op);
2465 operand *rv = (IS_ITEMP (op) ?
2466 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2468 sym_link *rvtype = operandType (rv);
2471 /* if this is not an address we have trouble */
2474 werror (E_LVALUE_REQUIRED, "++");
2478 rOp = newiTempOperand (rvtype, 0);
2479 OP_SYMBOL(rOp)->noSpilLoc = 1;
2482 OP_SYMBOL(rv)->noSpilLoc = 1;
2484 geniCodeAssign (rOp, rv, 0, 0);
2486 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2487 if (IS_FLOAT (rvtype))
2488 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2490 ic = newiCode ('+', rv, operandFromLit (size));
2492 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2495 geniCodeAssign (op, result, 0, 0);
2501 /*-----------------------------------------------------------------*/
2502 /* geniCodePreInc - generate code for preIncrement */
2503 /*-----------------------------------------------------------------*/
2505 geniCodePreInc (operand * op, bool lvalue)
2508 sym_link *optype = operandType (op);
2509 operand *rop = (IS_ITEMP (op) ?
2510 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2512 sym_link *roptype = operandType (rop);
2518 werror (E_LVALUE_REQUIRED, "++");
2523 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2524 if (IS_FLOAT (roptype))
2525 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2527 ic = newiCode ('+', rop, operandFromLit (size));
2528 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2531 (void) geniCodeAssign (op, result, 0, 0);
2532 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2538 /*-----------------------------------------------------------------*/
2539 /* geniCodePostDec - generates code for Post decrement */
2540 /*-----------------------------------------------------------------*/
2542 geniCodePostDec (operand * op)
2546 sym_link *optype = operandType (op);
2548 operand *rv = (IS_ITEMP (op) ?
2549 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2551 sym_link *rvtype = operandType (rv);
2554 /* if this is not an address we have trouble */
2557 werror (E_LVALUE_REQUIRED, "--");
2561 rOp = newiTempOperand (rvtype, 0);
2562 OP_SYMBOL(rOp)->noSpilLoc = 1;
2565 OP_SYMBOL(rv)->noSpilLoc = 1;
2567 geniCodeAssign (rOp, rv, 0, 0);
2569 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2570 if (IS_FLOAT (rvtype))
2571 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2573 ic = newiCode ('-', rv, operandFromLit (size));
2575 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2578 geniCodeAssign (op, result, 0, 0);
2584 /*-----------------------------------------------------------------*/
2585 /* geniCodePreDec - generate code for pre decrement */
2586 /*-----------------------------------------------------------------*/
2588 geniCodePreDec (operand * op, bool lvalue)
2591 sym_link *optype = operandType (op);
2592 operand *rop = (IS_ITEMP (op) ?
2593 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2595 sym_link *roptype = operandType (rop);
2601 werror (E_LVALUE_REQUIRED, "--");
2606 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2607 if (IS_FLOAT (roptype))
2608 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2610 ic = newiCode ('-', rop, operandFromLit (size));
2611 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2614 (void) geniCodeAssign (op, result, 0, 0);
2615 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2622 /*-----------------------------------------------------------------*/
2623 /* geniCodeBitwise - gen int code for bitWise operators */
2624 /*-----------------------------------------------------------------*/
2626 geniCodeBitwise (operand * left, operand * right,
2627 int oper, sym_link * resType)
2631 left = geniCodeCast (resType, left, TRUE);
2632 right = geniCodeCast (resType, right, TRUE);
2634 ic = newiCode (oper, left, right);
2635 IC_RESULT (ic) = newiTempOperand (resType, 0);
2638 return IC_RESULT (ic);
2641 /*-----------------------------------------------------------------*/
2642 /* geniCodeAddressOf - gens icode for '&' address of operator */
2643 /*-----------------------------------------------------------------*/
2645 geniCodeAddressOf (operand * op)
2649 sym_link *optype = operandType (op);
2650 sym_link *opetype = getSpec (optype);
2652 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2654 op = operandFromOperand (op);
2659 /* lvalue check already done in decorateType */
2660 /* this must be a lvalue */
2661 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2662 /* werror (E_LVALUE_REQUIRED,"&"); */
2666 p = newLink (DECLARATOR);
2668 /* set the pointer depending on the storage class */
2669 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2671 p->next = copyLinkChain (optype);
2673 /* if already a temp */
2676 setOperandType (op, p);
2681 /* other wise make this of the type coming in */
2682 ic = newiCode (ADDRESS_OF, op, NULL);
2683 IC_RESULT (ic) = newiTempOperand (p, 1);
2684 IC_RESULT (ic)->isaddr = 0;
2686 return IC_RESULT (ic);
2688 /*-----------------------------------------------------------------*/
2689 /* setOClass - sets the output class depending on the pointer type */
2690 /*-----------------------------------------------------------------*/
2692 setOClass (sym_link * ptr, sym_link * spec)
2694 switch (DCL_TYPE (ptr))
2697 SPEC_OCLS (spec) = data;
2701 SPEC_OCLS (spec) = generic;
2705 SPEC_OCLS (spec) = xdata;
2709 SPEC_OCLS (spec) = code;
2713 SPEC_OCLS (spec) = idata;
2717 SPEC_OCLS (spec) = xstack;
2721 SPEC_OCLS (spec) = eeprom;
2730 /*-----------------------------------------------------------------*/
2731 /* geniCodeDerefPtr - dereference pointer with '*' */
2732 /*-----------------------------------------------------------------*/
2734 geniCodeDerefPtr (operand * op,int lvl)
2736 sym_link *rtype, *retype;
2737 sym_link *optype = operandType (op);
2739 // if this is an array then array access
2740 if (IS_ARRAY (optype)) {
2741 // don't worry, this will be optimized out later
2742 return geniCodeArray (op, operandFromLit (0), lvl);
2745 // just in case someone screws up
2746 wassert (IS_PTR (optype));
2748 if (IS_TRUE_SYMOP (op))
2751 op = geniCodeRValue (op, TRUE);
2754 /* now get rid of the pointer part */
2755 if (isLvaluereq(lvl) && IS_ITEMP (op))
2757 retype = getSpec (rtype = copyLinkChain (optype));
2761 retype = getSpec (rtype = copyLinkChain (optype->next));
2762 /* outputclass needs 2b updated */
2763 setOClass (optype, retype);
2766 op->isGptr = IS_GENPTR (optype);
2768 op->isaddr = (IS_PTR (rtype) ||
2769 IS_STRUCT (rtype) ||
2774 if (!isLvaluereq(lvl))
2775 op = geniCodeRValue (op, TRUE);
2777 setOperandType (op, rtype);
2782 /*-----------------------------------------------------------------*/
2783 /* geniCodeUnaryMinus - does a unary minus of the operand */
2784 /*-----------------------------------------------------------------*/
2786 geniCodeUnaryMinus (operand * op)
2789 sym_link *optype = operandType (op);
2791 if (IS_LITERAL (optype))
2792 return operandFromLit (-floatFromVal (op->operand.valOperand));
2794 ic = newiCode (UNARYMINUS, op, NULL);
2795 IC_RESULT (ic) = newiTempOperand (optype, 0);
2797 return IC_RESULT (ic);
2800 /*-----------------------------------------------------------------*/
2801 /* geniCodeLeftShift - gen i code for left shift */
2802 /*-----------------------------------------------------------------*/
2804 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2809 ic = newiCode (LEFT_OP, left, right);
2811 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2812 IC_RESULT (ic) = newiTempOperand (resType, 0);
2814 return IC_RESULT (ic);
2817 /*-----------------------------------------------------------------*/
2818 /* geniCodeRightShift - gen i code for right shift */
2819 /*-----------------------------------------------------------------*/
2821 geniCodeRightShift (operand * left, operand * right)
2825 ic = newiCode (RIGHT_OP, left, right);
2826 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2828 return IC_RESULT (ic);
2831 /*-----------------------------------------------------------------*/
2832 /* geniCodeLogic- logic code */
2833 /*-----------------------------------------------------------------*/
2835 geniCodeLogic (operand * left, operand * right, int op)
2839 sym_link *rtype = operandType (right);
2840 sym_link *ltype = operandType (left);
2842 /* left is integral type and right is literal then
2843 check if the literal value is within bounds */
2844 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2846 checkConstantRange(ltype,
2847 OP_VALUE(right), "compare operation", 1);
2850 /* if one operand is a pointer and the other is a literal generic void pointer,
2851 change the type of the literal generic void pointer to match the other pointer */
2852 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2853 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2855 /* find left's definition */
2856 ic = (iCode *) setFirstItem (iCodeChain);
2859 if (((ic->op == CAST) || (ic->op == '='))
2860 && isOperandEqual(left, IC_RESULT (ic)))
2863 ic = setNextItem (iCodeChain);
2865 /* if casting literal to generic pointer, then cast to rtype instead */
2866 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2868 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2869 ltype = operandType(left);
2872 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2873 && IS_PTR (ltype) && !IS_GENPTR(ltype))
2875 /* find right's definition */
2876 ic = (iCode *) setFirstItem (iCodeChain);
2879 if (((ic->op == CAST) || (ic->op == '='))
2880 && isOperandEqual(right, IC_RESULT (ic)))
2883 ic = setNextItem (iCodeChain);
2885 /* if casting literal to generic pointer, then cast to rtype instead */
2886 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2888 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2889 rtype = operandType(right);
2893 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
2895 ic = newiCode (op, left, right);
2896 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2898 /* if comparing float
2899 and not a '==' || '!=' || '&&' || '||' (these
2901 if (IS_FLOAT(ctype) &&
2909 return IC_RESULT (ic);
2912 /*-----------------------------------------------------------------*/
2913 /* geniCodeLogicAndOr - && || operations */
2914 /*-----------------------------------------------------------------*/
2916 geniCodeLogicAndOr (ast *tree, int lvl)
2919 symbol *falseLabel = newiTempLabel (NULL);
2920 symbol *trueLabel = newiTempLabel (NULL);
2921 symbol *exitLabel = newiTempLabel (NULL);
2922 operand *op, *result, *condition;
2924 /* AND_OP and OR_OP are no longer generated because of bug-905492.
2925 They can be reenabled by executing the following block. If you find
2926 a decent optimization you could start right here:
2931 operand *leftOp, *rightOp;
2933 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
2934 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
2936 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
2940 /* generate two IFX for the '&&' or '||' op */
2942 /* evaluate left operand */
2943 condition = ast2iCode (tree->left, lvl + 1);
2944 op = geniCodeRValue (condition, FALSE);
2946 /* test left operand */
2947 if (tree->opval.op == AND_OP)
2948 ic = newiCodeCondition (op, NULL, falseLabel);
2950 ic = newiCodeCondition (op, trueLabel, NULL);
2953 /* evaluate right operand */
2954 condition = ast2iCode (tree->right, lvl + 1);
2955 op = geniCodeRValue (condition, FALSE);
2957 /* test right operand */
2958 ic = newiCodeCondition (op, trueLabel, NULL);
2961 /* store 0 or 1 in result */
2962 result = newiTempOperand (newCharLink(), 1);
2964 geniCodeLabel (falseLabel);
2965 geniCodeAssign (result, operandFromLit (0), 0, 0);
2966 /* generate an unconditional goto */
2967 geniCodeGoto (exitLabel);
2969 geniCodeLabel (trueLabel);
2970 geniCodeAssign (result, operandFromLit (1), 0, 0);
2972 geniCodeLabel (exitLabel);
2977 /*-----------------------------------------------------------------*/
2978 /* geniCodeUnary - for a a generic unary operation */
2979 /*-----------------------------------------------------------------*/
2981 geniCodeUnary (operand * op, int oper)
2983 iCode *ic = newiCode (oper, op, NULL);
2985 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2987 return IC_RESULT (ic);
2990 /*-----------------------------------------------------------------*/
2991 /* geniCodeConditional - geniCode for '?' ':' operation */
2992 /*-----------------------------------------------------------------*/
2994 geniCodeConditional (ast * tree,int lvl)
2997 symbol *falseLabel = newiTempLabel (NULL);
2998 symbol *exitLabel = newiTempLabel (NULL);
2999 operand *cond = ast2iCode (tree->left,lvl+1);
3000 operand *true, *false, *result;
3002 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3006 true = ast2iCode (tree->right->left,lvl+1);
3008 /* move the value to a new Operand */
3009 result = newiTempOperand (tree->right->ftype, 0);
3010 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3012 /* generate an unconditional goto */
3013 geniCodeGoto (exitLabel);
3015 /* now for the right side */
3016 geniCodeLabel (falseLabel);
3018 false = ast2iCode (tree->right->right,lvl+1);
3019 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3021 /* create the exit label */
3022 geniCodeLabel (exitLabel);
3027 /*-----------------------------------------------------------------*/
3028 /* geniCodeAssign - generate code for assignment */
3029 /*-----------------------------------------------------------------*/
3031 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3034 sym_link *ltype = operandType (left);
3035 sym_link *rtype = operandType (right);
3037 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3039 werror (E_LVALUE_REQUIRED, "assignment");
3043 /* left is integral type and right is literal then
3044 check if the literal value is within bounds */
3045 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3047 checkConstantRange(ltype,
3048 OP_VALUE(right), "= operation", 0);
3051 /* if the left & right type don't exactly match */
3052 /* if pointer set then make sure the check is
3053 done with the type & not the pointer */
3054 /* then cast rights type to left */
3056 /* first check the type for pointer assignement */
3057 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3058 compareType (ltype, rtype) <= 0)
3060 if (compareType (ltype->next, rtype) < 0)
3061 right = geniCodeCast (ltype->next, right, TRUE);
3063 else if (compareType (ltype, rtype) < 0)
3064 right = geniCodeCast (ltype, right, TRUE);
3066 /* If left is a true symbol & ! volatile
3067 create an assignment to temporary for
3068 the right & then assign this temporary
3069 to the symbol. This is SSA (static single
3070 assignment). Isn't it simple and folks have
3071 published mountains of paper on it */
3072 if (IS_TRUE_SYMOP (left) &&
3073 !isOperandVolatile (left, FALSE) &&
3074 isOperandGlobal (left))
3078 if (IS_TRUE_SYMOP (right))
3079 sym = OP_SYMBOL (right);
3080 ic = newiCode ('=', NULL, right);
3081 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3082 SPIL_LOC (right) = sym;
3086 ic = newiCode ('=', NULL, right);
3087 IC_RESULT (ic) = left;
3090 /* if left isgptr flag is set then support
3091 routine will be required */
3095 ic->nosupdate = nosupdate;
3099 /*-----------------------------------------------------------------*/
3100 /* geniCodeDummyRead - generate code for dummy read */
3101 /*-----------------------------------------------------------------*/
3103 geniCodeDummyRead (operand * op)
3106 sym_link *type = operandType (op);
3108 if (!IS_VOLATILE(type))
3111 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3117 /*-----------------------------------------------------------------*/
3118 /* geniCodeSEParms - generate code for side effecting fcalls */
3119 /*-----------------------------------------------------------------*/
3121 geniCodeSEParms (ast * parms,int lvl)
3126 if (parms->type == EX_OP && parms->opval.op == PARAM)
3128 geniCodeSEParms (parms->left,lvl);
3129 geniCodeSEParms (parms->right,lvl);
3133 /* hack don't like this but too lazy to think of
3135 if (IS_ADDRESS_OF_OP (parms))
3136 parms->left->lvalue = 1;
3138 if (IS_CAST_OP (parms) &&
3139 IS_PTR (parms->ftype) &&
3140 IS_ADDRESS_OF_OP (parms->right))
3141 parms->right->left->lvalue = 1;
3143 parms->opval.oprnd =
3144 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3146 parms->type = EX_OPERAND;
3147 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3148 SPEC_ARGREG(parms->ftype);
3151 /*-----------------------------------------------------------------*/
3152 /* geniCodeParms - generates parameters */
3153 /*-----------------------------------------------------------------*/
3155 geniCodeParms (ast * parms, value *argVals, int *stack,
3156 sym_link * ftype, int lvl)
3164 if (argVals==NULL) {
3166 argVals = FUNC_ARGS (ftype);
3169 /* if this is a param node then do the left & right */
3170 if (parms->type == EX_OP && parms->opval.op == PARAM)
3172 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3173 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3177 /* get the parameter value */
3178 if (parms->type == EX_OPERAND)
3179 pval = parms->opval.oprnd;
3182 /* maybe this else should go away ?? */
3183 /* hack don't like this but too lazy to think of
3185 if (IS_ADDRESS_OF_OP (parms))
3186 parms->left->lvalue = 1;
3188 if (IS_CAST_OP (parms) &&
3189 IS_PTR (parms->ftype) &&
3190 IS_ADDRESS_OF_OP (parms->right))
3191 parms->right->left->lvalue = 1;
3193 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3196 /* if register parm then make it a send */
3197 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3198 IFFUNC_ISBUILTIN(ftype))
3200 ic = newiCode (SEND, pval, NULL);
3201 ic->argreg = SPEC_ARGREG(parms->etype);
3202 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3207 /* now decide whether to push or assign */
3208 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3212 operand *top = operandFromSymbol (argVals->sym);
3213 /* clear useDef and other bitVectors */
3214 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3215 geniCodeAssign (top, pval, 1, 0);
3219 sym_link *p = operandType (pval);
3221 ic = newiCode (IPUSH, pval, NULL);
3223 /* update the stack adjustment */
3224 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3229 argVals=argVals->next;
3233 /*-----------------------------------------------------------------*/
3234 /* geniCodeCall - generates temp code for calling */
3235 /*-----------------------------------------------------------------*/
3237 geniCodeCall (operand * left, ast * parms,int lvl)
3241 sym_link *type, *etype;
3245 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3246 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3247 werror (E_FUNCTION_EXPECTED);
3248 return operandFromValue(valueFromLit(0));
3251 /* take care of parameters with side-effecting
3252 function calls in them, this is required to take care
3253 of overlaying function parameters */
3254 geniCodeSEParms (parms,lvl);
3256 ftype = operandType (left);
3257 if (IS_CODEPTR (ftype))
3258 ftype = ftype->next;
3260 /* first the parameters */
3261 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3263 /* now call : if symbol then pcall */
3264 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3265 ic = newiCode (PCALL, left, NULL);
3267 ic = newiCode (CALL, left, NULL);
3270 type = copyLinkChain (ftype->next);
3271 etype = getSpec (type);
3272 SPEC_EXTR (etype) = 0;
3273 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3277 /* stack adjustment after call */
3278 ic->parmBytes = stack;
3283 /*-----------------------------------------------------------------*/
3284 /* geniCodeReceive - generate intermediate code for "receive" */
3285 /*-----------------------------------------------------------------*/
3287 geniCodeReceive (value * args)
3289 /* for all arguments that are passed in registers */
3293 if (IS_REGPARM (args->etype))
3295 operand *opr = operandFromValue (args);
3297 symbol *sym = OP_SYMBOL (opr);
3300 /* we will use it after all optimizations
3301 and before liveRange calculation */
3302 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3305 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3306 options.stackAuto == 0 &&
3307 (!(options.model == MODEL_FLAT24)) )
3312 opl = newiTempOperand (args->type, 0);
3314 sym->reqv->key = sym->key;
3315 OP_SYMBOL (sym->reqv)->key = sym->key;
3316 OP_SYMBOL (sym->reqv)->isreqv = 1;
3317 OP_SYMBOL (sym->reqv)->islocal = 0;
3318 SPIL_LOC (sym->reqv) = sym;
3322 ic = newiCode (RECEIVE, NULL, NULL);
3323 ic->argreg = SPEC_ARGREG(args->etype);
3325 currFunc->recvSize = getSize (sym->type);
3328 IC_RESULT (ic) = opr;
3336 /*-----------------------------------------------------------------*/
3337 /* geniCodeFunctionBody - create the function body */
3338 /*-----------------------------------------------------------------*/
3340 geniCodeFunctionBody (ast * tree,int lvl)
3347 /* reset the auto generation */
3353 func = ast2iCode (tree->left,lvl+1);
3354 fetype = getSpec (operandType (func));
3356 savelineno = lineno;
3357 lineno = OP_SYMBOL (func)->lineDef;
3358 /* create an entry label */
3359 geniCodeLabel (entryLabel);
3360 lineno = savelineno;
3362 /* create a proc icode */
3363 ic = newiCode (FUNCTION, func, NULL);
3364 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3369 /* for all parameters that are passed
3370 on registers add a "receive" */
3371 geniCodeReceive (tree->values.args);
3373 /* generate code for the body */
3374 ast2iCode (tree->right,lvl+1);
3376 /* create a label for return */
3377 geniCodeLabel (returnLabel);
3379 /* now generate the end proc */
3380 ic = newiCode (ENDFUNCTION, func, NULL);
3386 /*-----------------------------------------------------------------*/
3387 /* geniCodeReturn - gen icode for 'return' statement */
3388 /*-----------------------------------------------------------------*/
3390 geniCodeReturn (operand * op)
3394 /* if the operand is present force an rvalue */
3396 op = geniCodeRValue (op, FALSE);
3398 ic = newiCode (RETURN, op, NULL);
3402 /*-----------------------------------------------------------------*/
3403 /* geniCodeIfx - generates code for extended if statement */
3404 /*-----------------------------------------------------------------*/
3406 geniCodeIfx (ast * tree,int lvl)
3409 operand *condition = ast2iCode (tree->left,lvl+1);
3412 /* if condition is null then exit */
3416 condition = geniCodeRValue (condition, FALSE);
3418 cetype = getSpec (operandType (condition));
3419 /* if the condition is a literal */
3420 if (IS_LITERAL (cetype))
3422 if (floatFromVal (condition->operand.valOperand))
3424 if (tree->trueLabel)
3425 geniCodeGoto (tree->trueLabel);
3431 if (tree->falseLabel)
3432 geniCodeGoto (tree->falseLabel);
3439 if (tree->trueLabel)
3441 ic = newiCodeCondition (condition,
3446 if (tree->falseLabel)
3447 geniCodeGoto (tree->falseLabel);
3451 ic = newiCodeCondition (condition,
3458 ast2iCode (tree->right,lvl+1);
3461 /*-----------------------------------------------------------------*/
3462 /* geniCodeJumpTable - tries to create a jump table for switch */
3463 /*-----------------------------------------------------------------*/
3465 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3467 int min = 0, max = 0, t, cnt = 0;
3473 int needRangeCheck = !optimize.noJTabBoundary
3474 || tree->values.switchVals.swDefault;
3476 if (!tree || !caseVals)
3479 /* the criteria for creating a jump table is */
3480 /* all integer numbers between the maximum & minimum must */
3481 /* be present , the maximum value should not exceed 255 */
3482 min = max = (int) floatFromVal (vch = caseVals);
3483 SNPRINTF (buffer, sizeof(buffer),
3485 tree->values.switchVals.swNum,
3487 addSet (&labels, newiTempLabel (buffer));
3489 /* if there is only one case value then no need */
3490 if (!(vch = vch->next))
3495 if (((t = (int) floatFromVal (vch)) - max) != 1)
3497 SNPRINTF (buffer, sizeof(buffer),
3499 tree->values.switchVals.swNum,
3501 addSet (&labels, newiTempLabel (buffer));
3507 /* if the number of case statements <= 2 then */
3508 /* it is not economical to create the jump table */
3509 /* since two compares are needed for boundary conditions */
3510 if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
3513 if (tree->values.switchVals.swDefault)
3515 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3519 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3523 falseLabel = newiTempLabel (buffer);
3525 /* If cond is volatile, it might change after the boundary */
3526 /* conditions are tested to an out of bounds value, causing */
3527 /* a jump to a location outside of the jump table. To avoid */
3528 /* this possibility, use a non-volatile copy of it instead. */
3529 if (IS_OP_VOLATILE (cond))
3534 newcond = newiTempOperand (operandType (cond), TRUE);
3535 newcond->isvolatile = 0;
3536 ic = newiCode ('=', NULL, cond);
3537 IC_RESULT (ic) = newcond;
3542 /* so we can create a jumptable */
3543 /* first we rule out the boundary conditions */
3544 /* if only optimization says so */
3547 sym_link *cetype = getSpec (operandType (cond));
3548 /* no need to check the lower bound if
3549 the condition is unsigned & minimum value is zero */
3550 if (!(min == 0 && IS_UNSIGNED (cetype)))
3552 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3553 ic = newiCodeCondition (boundary, falseLabel, NULL);
3557 /* now for upper bounds */
3558 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3559 ic = newiCodeCondition (boundary, falseLabel, NULL);
3563 /* if the min is not zero then we no make it zero */
3566 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3567 if (!IS_LITERAL(getSpec(operandType(cond))))
3568 setOperandType (cond, UCHARTYPE);
3571 /* now create the jumptable */
3572 ic = newiCode (JUMPTABLE, NULL, NULL);
3573 IC_JTCOND (ic) = cond;
3574 IC_JTLABELS (ic) = labels;
3579 /*-----------------------------------------------------------------*/
3580 /* geniCodeSwitch - changes a switch to a if statement */
3581 /*-----------------------------------------------------------------*/
3583 geniCodeSwitch (ast * tree,int lvl)
3586 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3587 value *caseVals = tree->values.switchVals.swVals;
3588 symbol *trueLabel, *falseLabel;
3590 /* If the condition is a literal, then just jump to the */
3591 /* appropriate case label. */
3592 if (IS_LITERAL(getSpec(operandType(cond))))
3594 int switchVal, caseVal;
3596 switchVal = (int) floatFromVal (cond->operand.valOperand);
3599 caseVal = (int) floatFromVal (caseVals);
3600 if (caseVal == switchVal)
3602 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3603 tree->values.switchVals.swNum, caseVal);
3604 trueLabel = newiTempLabel (buffer);
3605 geniCodeGoto (trueLabel);
3608 caseVals = caseVals->next;
3610 goto defaultOrBreak;
3613 /* if we can make this a jump table */
3614 if (geniCodeJumpTable (cond, caseVals, tree))
3615 goto jumpTable; /* no need for the comparison */
3617 /* for the cases defined do */
3621 operand *compare = geniCodeLogic (cond,
3622 operandFromValue (caseVals),
3625 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3626 tree->values.switchVals.swNum,
3627 (int) floatFromVal (caseVals));
3628 trueLabel = newiTempLabel (buffer);
3630 ic = newiCodeCondition (compare, trueLabel, NULL);
3632 caseVals = caseVals->next;
3637 /* if default is present then goto break else break */
3638 if (tree->values.switchVals.swDefault)
3640 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3644 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3647 falseLabel = newiTempLabel (buffer);
3648 geniCodeGoto (falseLabel);
3651 ast2iCode (tree->right,lvl+1);
3654 /*-----------------------------------------------------------------*/
3655 /* geniCodeInline - intermediate code for inline assembler */
3656 /*-----------------------------------------------------------------*/
3658 geniCodeInline (ast * tree)
3662 ic = newiCode (INLINEASM, NULL, NULL);
3663 IC_INLINE (ic) = tree->values.inlineasm;
3667 /*-----------------------------------------------------------------*/
3668 /* geniCodeArrayInit - intermediate code for array initializer */
3669 /*-----------------------------------------------------------------*/
3671 geniCodeArrayInit (ast * tree, operand *array)
3675 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3676 ic = newiCode (ARRAYINIT, array, NULL);
3677 IC_ARRAYILIST (ic) = tree->values.constlist;
3679 operand *left=newOperand(), *right=newOperand();
3680 left->type=right->type=SYMBOL;
3681 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3682 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3683 ic = newiCode (ARRAYINIT, left, right);
3688 /*-----------------------------------------------------------------*/
3689 /* geniCodeCritical - intermediate code for a critical statement */
3690 /*-----------------------------------------------------------------*/
3692 geniCodeCritical (ast *tree, int lvl)
3697 /* If op is NULL, the original interrupt state will saved on */
3698 /* the stack. Otherwise, it will be saved in op. */
3700 /* Generate a save of the current interrupt state & disabled */
3701 ic = newiCode (CRITICAL, NULL, NULL);
3702 IC_RESULT (ic) = op;
3705 /* Generate the critical code sequence */
3706 if (tree->left && tree->left->type == EX_VALUE)
3707 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3709 ast2iCode (tree->left,lvl+1);
3711 /* Generate a restore of the original interrupt state */
3712 ic = newiCode (ENDCRITICAL, NULL, op);
3716 /*-----------------------------------------------------------------*/
3717 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3718 /* particular case. Ie : assigning or dereferencing array or ptr */
3719 /*-----------------------------------------------------------------*/
3720 set * lvaluereqSet = NULL;
3721 typedef struct lvalItem
3728 /*-----------------------------------------------------------------*/
3729 /* addLvaluereq - add a flag for lvalreq for current ast level */
3730 /*-----------------------------------------------------------------*/
3731 void addLvaluereq(int lvl)
3733 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3736 addSetHead(&lvaluereqSet,lpItem);
3739 /*-----------------------------------------------------------------*/
3740 /* delLvaluereq - del a flag for lvalreq for current ast level */
3741 /*-----------------------------------------------------------------*/
3745 lpItem = getSet(&lvaluereqSet);
3746 if(lpItem) Safe_free(lpItem);
3748 /*-----------------------------------------------------------------*/
3749 /* clearLvaluereq - clear lvalreq flag */
3750 /*-----------------------------------------------------------------*/
3751 void clearLvaluereq()
3754 lpItem = peekSet(lvaluereqSet);
3755 if(lpItem) lpItem->req = 0;
3757 /*-----------------------------------------------------------------*/
3758 /* getLvaluereq - get the last lvalreq level */
3759 /*-----------------------------------------------------------------*/
3760 int getLvaluereqLvl()
3763 lpItem = peekSet(lvaluereqSet);
3764 if(lpItem) return lpItem->lvl;
3767 /*-----------------------------------------------------------------*/
3768 /* isLvaluereq - is lvalreq valid for this level ? */
3769 /*-----------------------------------------------------------------*/
3770 int isLvaluereq(int lvl)
3773 lpItem = peekSet(lvaluereqSet);
3774 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3778 /*-----------------------------------------------------------------*/
3779 /* ast2iCode - creates an icodeList from an ast */
3780 /*-----------------------------------------------------------------*/
3782 ast2iCode (ast * tree,int lvl)
3784 operand *left = NULL;
3785 operand *right = NULL;
3789 /* set the global variables for filename & line number */
3791 filename = tree->filename;
3793 lineno = tree->lineno;
3795 block = tree->block;
3797 scopeLevel = tree->level;
3799 seqPoint = tree->seqPoint;
3801 if (tree->type == EX_VALUE)
3802 return operandFromValue (tree->opval.val);
3804 if (tree->type == EX_LINK)
3805 return operandFromLink (tree->opval.lnk);
3807 /* if we find a nullop */
3808 if (tree->type == EX_OP &&
3809 (tree->opval.op == NULLOP ||
3810 tree->opval.op == BLOCK))
3812 if (tree->left && tree->left->type == EX_VALUE)
3813 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3815 ast2iCode (tree->left,lvl+1);
3816 if (tree->right && tree->right->type == EX_VALUE)
3817 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3819 ast2iCode (tree->right,lvl+1);
3823 /* special cases for not evaluating */
3824 if (tree->opval.op != ':' &&
3825 tree->opval.op != '?' &&
3826 tree->opval.op != CALL &&
3827 tree->opval.op != IFX &&
3828 tree->opval.op != AND_OP &&
3829 tree->opval.op != OR_OP &&
3830 tree->opval.op != LABEL &&
3831 tree->opval.op != GOTO &&
3832 tree->opval.op != SWITCH &&
3833 tree->opval.op != FUNCTION &&
3834 tree->opval.op != INLINEASM &&
3835 tree->opval.op != CRITICAL)
3838 if (IS_ASSIGN_OP (tree->opval.op) ||
3839 IS_DEREF_OP (tree) ||
3840 (tree->opval.op == '&' && !tree->right) ||
3841 tree->opval.op == PTR_OP)
3844 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3845 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3848 left = operandFromAst (tree->left,lvl);
3850 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3851 left = geniCodeRValue (left, TRUE);
3855 left = operandFromAst (tree->left,lvl);
3857 if (tree->opval.op == INC_OP ||
3858 tree->opval.op == DEC_OP)
3861 right = operandFromAst (tree->right,lvl);
3866 right = operandFromAst (tree->right,lvl);
3870 /* now depending on the type of operand */
3871 /* this will be a biggy */
3872 switch (tree->opval.op)
3875 case '[': /* array operation */
3877 //sym_link *ltype = operandType (left);
3878 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3879 left = geniCodeRValue (left, FALSE);
3880 right = geniCodeRValue (right, TRUE);
3883 return geniCodeArray (left, right,lvl);
3885 case '.': /* structure dereference */
3886 if (IS_PTR (operandType (left)))
3887 left = geniCodeRValue (left, TRUE);
3889 left = geniCodeRValue (left, FALSE);
3891 return geniCodeStruct (left, right, tree->lvalue);
3893 case PTR_OP: /* structure pointer dereference */
3896 pType = operandType (left);
3897 left = geniCodeRValue (left, TRUE);
3899 setOClass (pType, getSpec (operandType (left)));
3902 return geniCodeStruct (left, right, tree->lvalue);
3904 case INC_OP: /* increment operator */
3906 return geniCodePostInc (left);
3908 return geniCodePreInc (right, tree->lvalue);
3910 case DEC_OP: /* decrement operator */
3912 return geniCodePostDec (left);
3914 return geniCodePreDec (right, tree->lvalue);
3916 case '&': /* bitwise and or address of operator */
3918 { /* this is a bitwise operator */
3919 left = geniCodeRValue (left, FALSE);
3920 right = geniCodeRValue (right, FALSE);
3921 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3924 return geniCodeAddressOf (left);
3926 case '|': /* bitwise or & xor */
3928 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3929 geniCodeRValue (right, FALSE),
3934 return geniCodeDivision (geniCodeRValue (left, FALSE),
3935 geniCodeRValue (right, FALSE),
3936 getResultTypeFromType (tree->ftype));
3939 return geniCodeModulus (geniCodeRValue (left, FALSE),
3940 geniCodeRValue (right, FALSE),
3941 getResultTypeFromType (tree->ftype));
3944 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3945 geniCodeRValue (right, FALSE),
3946 getResultTypeFromType (tree->ftype));
3948 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3952 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3953 geniCodeRValue (right, FALSE),
3954 getResultTypeFromType (tree->ftype));
3956 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3960 return geniCodeAdd (geniCodeRValue (left, FALSE),
3961 geniCodeRValue (right, FALSE),
3962 getResultTypeFromType (tree->ftype),
3965 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3968 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3969 geniCodeRValue (right, FALSE),
3970 getResultTypeFromType (tree->ftype));
3973 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3974 geniCodeRValue (right, FALSE));
3976 #if 0 // this indeed needs a second thought
3980 // let's keep this simple: get the rvalue we need
3981 op=geniCodeRValue (right, FALSE);
3982 // now cast it to whatever we want
3983 op=geniCodeCast (operandType(left), op, FALSE);
3984 // if this is going to be used as an lvalue, make it so
3990 #else // bug #604575, is it a bug ????
3991 return geniCodeCast (operandType (left),
3992 geniCodeRValue (right, FALSE), FALSE);
3999 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4004 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4005 setOperandType (op, UCHARTYPE);
4010 return geniCodeLogicAndOr (tree, lvl);
4017 /* different compilers (even different gccs) evaluate
4018 the two calls in a different order. to get the same
4019 result on all machines we've to specify a clear sequence.
4020 return geniCodeLogic (geniCodeRValue (left, FALSE),
4021 geniCodeRValue (right, FALSE),
4025 operand *leftOp, *rightOp;
4027 leftOp = geniCodeRValue (left , FALSE);
4028 rightOp = geniCodeRValue (right, FALSE);
4030 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4033 return geniCodeConditional (tree,lvl);
4036 return operandFromLit (getSize (tree->right->ftype));
4040 sym_link *rtype = operandType (right);
4041 sym_link *ltype = operandType (left);
4042 if (IS_PTR (rtype) && IS_ITEMP (right)
4043 && right->isaddr && compareType (rtype->next, ltype) == 1)
4044 right = geniCodeRValue (right, TRUE);
4046 right = geniCodeRValue (right, FALSE);
4048 geniCodeAssign (left, right, 0, 1);
4053 geniCodeAssign (left,
4054 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4056 geniCodeRValue (right, FALSE),
4057 getResultTypeFromType (tree->ftype)),
4062 geniCodeAssign (left,
4063 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4065 geniCodeRValue (right, FALSE),
4066 getResultTypeFromType (tree->ftype)),
4070 geniCodeAssign (left,
4071 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4073 geniCodeRValue (right, FALSE),
4074 getResultTypeFromType (tree->ftype)),
4078 sym_link *rtype = operandType (right);
4079 sym_link *ltype = operandType (left);
4080 if (IS_PTR (rtype) && IS_ITEMP (right)
4081 && right->isaddr && compareType (rtype->next, ltype) == 1)
4082 right = geniCodeRValue (right, TRUE);
4084 right = geniCodeRValue (right, FALSE);
4087 return geniCodeAssign (left,
4088 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4091 getResultTypeFromType (tree->ftype),
4097 sym_link *rtype = operandType (right);
4098 sym_link *ltype = operandType (left);
4099 if (IS_PTR (rtype) && IS_ITEMP (right)
4100 && right->isaddr && compareType (rtype->next, ltype) == 1)
4102 right = geniCodeRValue (right, TRUE);
4106 right = geniCodeRValue (right, FALSE);
4109 geniCodeAssign (left,
4110 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4113 getResultTypeFromType (tree->ftype)),
4118 geniCodeAssign (left,
4119 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4121 geniCodeRValue (right, FALSE),
4122 getResultTypeFromType (tree->ftype)),
4126 geniCodeAssign (left,
4127 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4129 geniCodeRValue (right, FALSE)), 0, 1);
4132 geniCodeAssign (left,
4133 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4135 geniCodeRValue (right, FALSE),
4137 operandType (left)), 0, 1);
4140 geniCodeAssign (left,
4141 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4143 geniCodeRValue (right, FALSE),
4145 operandType (left)), 0, 1);
4148 geniCodeAssign (left,
4149 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4151 geniCodeRValue (right, FALSE),
4153 operandType (left)), 0, 1);
4155 return geniCodeRValue (right, FALSE);
4158 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4161 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4162 return ast2iCode (tree->right,lvl+1);
4165 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4166 return ast2iCode (tree->right,lvl+1);
4169 geniCodeFunctionBody (tree,lvl);
4173 geniCodeReturn (right);
4177 geniCodeIfx (tree,lvl);
4181 geniCodeSwitch (tree,lvl);
4185 geniCodeInline (tree);
4189 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4193 geniCodeCritical (tree, lvl);
4199 /*-----------------------------------------------------------------*/
4200 /* reverseICChain - gets from the list and creates a linkedlist */
4201 /*-----------------------------------------------------------------*/
4208 while ((loop = getSet (&iCodeChain)))
4220 /*-----------------------------------------------------------------*/
4221 /* iCodeFromAst - given an ast will convert it to iCode */
4222 /*-----------------------------------------------------------------*/
4224 iCodeFromAst (ast * tree)
4226 returnLabel = newiTempLabel ("_return");
4227 entryLabel = newiTempLabel ("_entry");
4229 return reverseiCChain ();
4232 static const char *opTypeToStr(OPTYPE op)
4236 case SYMBOL: return "symbol";
4237 case VALUE: return "value";
4238 case TYPE: return "type";
4240 return "undefined type";
4244 operand *validateOpType(operand *op,
4251 if (op && op->type == type)
4256 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4257 " expected %s, got %s\n",
4258 macro, args, file, line,
4259 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4261 return op; // never reached, makes compiler happy.