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 {GETABIT, "gabit", picGenericOne, NULL},
84 {GETBYTE, "gbyte", picGenericOne, NULL},
85 {GETWORD, "gword", picGenericOne, NULL},
86 {UNARYMINUS, "-", picGenericOne, NULL},
87 {IPUSH, "push", picGenericOne, NULL},
88 {IPOP, "pop", picGenericOne, NULL},
89 {CALL, "call", picGenericOne, NULL},
90 {PCALL, "pcall", picGenericOne, NULL},
91 {FUNCTION, "proc", picGenericOne, NULL},
92 {ENDFUNCTION, "eproc", picGenericOne, NULL},
93 {RETURN, "ret", picGenericOne, NULL},
94 {'+', "+", picGeneric, NULL},
95 {'-', "-", picGeneric, NULL},
96 {'*', "*", picGeneric, NULL},
97 {'/', "/", picGeneric, NULL},
98 {'%', "%", picGeneric, NULL},
99 {'>', ">", picGeneric, NULL},
100 {'<', "<", picGeneric, NULL},
101 {LE_OP, "<=", picGeneric, NULL},
102 {GE_OP, ">=", picGeneric, NULL},
103 {EQ_OP, "==", picGeneric, NULL},
104 {NE_OP, "!=", picGeneric, NULL},
105 {AND_OP, "&&", picGeneric, NULL},
106 {OR_OP, "||", picGeneric, NULL},
107 {'^', "^", picGeneric, NULL},
108 {'|', "|", picGeneric, NULL},
109 {BITWISEAND, "&", picGeneric, NULL},
110 {LEFT_OP, "<<", picGeneric, NULL},
111 {RIGHT_OP, ">>", picGeneric, NULL},
112 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
113 {ADDRESS_OF, "&", picAddrOf, NULL},
114 {CAST, "<>", picCast, NULL},
115 {'=', ":=", picAssign, NULL},
116 {LABEL, "", picLabel, NULL},
117 {GOTO, "", picGoto, NULL},
118 {JUMPTABLE, "jtab", picJumpTable, NULL},
119 {IFX, "if", picIfx, NULL},
120 {INLINEASM, "", picInline, NULL},
121 {RECEIVE, "recv", picReceive, NULL},
122 {SEND, "send", picGenericOne, NULL},
123 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
124 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
125 {CRITICAL, "critical_start", picCritical, NULL},
126 {ENDCRITICAL, "critical_end", picEndCritical, NULL},
127 {SWAP, "swap", picGenericOne, NULL}
130 /*-----------------------------------------------------------------*/
131 /* operandName - returns the name of the operand */
132 /*-----------------------------------------------------------------*/
134 printOperand (operand * op, FILE * file)
151 opetype = getSpec (operandType (op));
152 if (IS_FLOAT (opetype))
153 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
154 else if (IS_FIXED16X16 (opetype))
155 fprintf (file, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
157 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
158 printTypeChain (operandType (op), file);
165 if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
166 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%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}" , */
167 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
169 OP_LIVEFROM (op), OP_LIVETO (op),
170 OP_SYMBOL (op)->stack,
171 op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
172 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
173 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
177 printTypeChain (operandType (op), file);
178 if (SPIL_LOC (op) && IS_ITEMP (op))
179 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
184 /* if assigned to registers */
185 if (OP_SYMBOL (op)->nRegs)
187 if (OP_SYMBOL (op)->isspilt)
189 if (!OP_SYMBOL (op)->remat)
190 if (OP_SYMBOL (op)->usl.spillLoc)
191 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
192 OP_SYMBOL (op)->usl.spillLoc->rname :
193 OP_SYMBOL (op)->usl.spillLoc->name));
195 fprintf (file, "[err]");
197 fprintf (file, "[remat]");
203 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
204 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
208 //#else /* } else { */
210 /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
211 fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
213 if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
215 fprintf (file, "[lr%d:%d so:%d]",
216 OP_LIVEFROM (op), OP_LIVETO (op),
217 OP_SYMBOL (op)->stack);
220 if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
223 printTypeChain (operandType (op), file);
224 if (SPIL_LOC (op) && IS_ITEMP (op))
225 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
229 /* if assigned to registers */
230 if (OP_SYMBOL (op)->nRegs)
232 if (OP_SYMBOL (op)->isspilt)
234 if (!OP_SYMBOL (op)->remat)
235 if (OP_SYMBOL (op)->usl.spillLoc)
236 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
237 OP_SYMBOL (op)->usl.spillLoc->rname :
238 OP_SYMBOL (op)->usl.spillLoc->name));
240 fprintf (file, "[err]");
242 fprintf (file, "[remat]");
248 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
249 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
259 printTypeChain (op->operand.typeOperand, file);
265 fprintf (file, "\n");
270 /*-----------------------------------------------------------------*/
271 /* print functions */
272 /*-----------------------------------------------------------------*/
273 PRINTFUNC (picGetValueAtAddr)
276 printOperand (IC_RESULT (ic), of);
279 printOperand (IC_LEFT (ic), of);
285 PRINTFUNC (picSetValueAtAddr)
289 printOperand (IC_LEFT (ic), of);
290 fprintf (of, "] = ");
291 printOperand (IC_RIGHT (ic), of);
295 PRINTFUNC (picAddrOf)
298 printOperand (IC_RESULT (ic), of);
299 if (IS_ITEMP (IC_LEFT (ic)))
302 fprintf (of, " = &[");
303 printOperand (IC_LEFT (ic), of);
306 if (IS_ITEMP (IC_LEFT (ic)))
307 fprintf (of, " offsetAdd ");
310 printOperand (IC_RIGHT (ic), of);
312 if (IS_ITEMP (IC_LEFT (ic)))
318 PRINTFUNC (picJumpTable)
323 fprintf (of, "%s\t", s);
324 printOperand (IC_JTCOND (ic), of);
326 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
327 sym = setNextItem (IC_JTLABELS (ic)))
328 fprintf (of, "\t\t\t%s\n", sym->name);
331 PRINTFUNC (picGeneric)
334 printOperand (IC_RESULT (ic), of);
336 printOperand (IC_LEFT (ic), of);
337 fprintf (of, " %s ", s);
338 printOperand (IC_RIGHT (ic), of);
342 PRINTFUNC (picGenericOne)
347 printOperand (IC_RESULT (ic), of);
353 fprintf (of, "%s ", s);
354 printOperand (IC_LEFT (ic), of);
357 if (!IC_RESULT (ic) && !IC_LEFT (ic))
360 if (ic->op == SEND || ic->op == RECEIVE) {
361 fprintf(of,"{argreg = %d}",ic->argreg);
363 if (ic->op == IPUSH) {
364 fprintf(of,"{parmPush = %d}",ic->parmPush);
372 printOperand (IC_RESULT (ic), of);
374 printOperand (IC_LEFT (ic), of);
375 printOperand (IC_RIGHT (ic), of);
380 PRINTFUNC (picAssign)
384 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
387 printOperand (IC_RESULT (ic), of);
389 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
392 fprintf (of, " %s ", s);
393 printOperand (IC_RIGHT (ic), of);
400 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
406 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
413 printOperand (IC_COND (ic), of);
416 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
419 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
421 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
425 PRINTFUNC (picInline)
427 fprintf (of, "%s", IC_INLINE (ic));
430 PRINTFUNC (picReceive)
432 printOperand (IC_RESULT (ic), of);
433 fprintf (of, " = %s ", s);
434 printOperand (IC_LEFT (ic), of);
438 PRINTFUNC (picDummyRead)
441 fprintf (of, "%s ", s);
442 printOperand (IC_RIGHT (ic), of);
446 PRINTFUNC (picCritical)
450 printOperand (IC_RESULT (ic), of);
452 fprintf (of, "(stack)");
453 fprintf (of, " = %s ", s);
457 PRINTFUNC (picEndCritical)
460 fprintf (of, "%s = ", s);
462 printOperand (IC_RIGHT (ic), of);
464 fprintf (of, "(stack)");
468 /*-----------------------------------------------------------------*/
469 /* piCode - prints one iCode */
470 /*-----------------------------------------------------------------*/
472 piCode (void *item, FILE * of)
480 icTab = getTableEntry (ic->op);
481 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
482 ic->filename, ic->lineno,
483 ic->seq, ic->key, ic->depth, ic->supportRtn);
484 icTab->iCodePrint (of, ic, icTab->printName);
490 printiCChain(ic,stdout);
492 /*-----------------------------------------------------------------*/
493 /* printiCChain - prints intermediate code for humans */
494 /*-----------------------------------------------------------------*/
496 printiCChain (iCode * icChain, FILE * of)
503 for (loop = icChain; loop; loop = loop->next)
505 if ((icTab = getTableEntry (loop->op)))
507 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
508 loop->filename, loop->lineno,
509 loop->seq, loop->key, loop->depth, loop->supportRtn);
511 icTab->iCodePrint (of, loop, icTab->printName);
517 /*-----------------------------------------------------------------*/
518 /* newOperand - allocate, init & return a new iCode */
519 /*-----------------------------------------------------------------*/
525 op = Safe_alloc ( sizeof (operand));
531 /*-----------------------------------------------------------------*/
532 /* newiCode - create and return a new iCode entry initialised */
533 /*-----------------------------------------------------------------*/
535 newiCode (int op, operand * left, operand * right)
539 ic = Safe_alloc ( sizeof (iCode));
541 ic->seqPoint = seqPoint;
543 ic->filename = filename;
545 ic->level = scopeLevel;
547 ic->key = iCodeKey++;
549 IC_RIGHT (ic) = right;
554 /*-----------------------------------------------------------------*/
555 /* newiCode for conditional statements */
556 /*-----------------------------------------------------------------*/
558 newiCodeCondition (operand * condition,
564 if (IS_VOID(operandType(condition))) {
565 werror(E_VOID_VALUE_USED);
568 ic = newiCode (IFX, NULL, NULL);
569 IC_COND (ic) = condition;
570 IC_TRUE (ic) = trueLabel;
571 IC_FALSE (ic) = falseLabel;
575 /*-----------------------------------------------------------------*/
576 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
577 /*-----------------------------------------------------------------*/
579 newiCodeLabelGoto (int op, symbol * label)
583 ic = newiCode (op, NULL, NULL);
587 IC_RIGHT (ic) = NULL;
588 IC_RESULT (ic) = NULL;
592 /*-----------------------------------------------------------------*/
593 /* newiTemp - allocate & return a newItemp Variable */
594 /*-----------------------------------------------------------------*/
602 SNPRINTF (buffer, sizeof(buffer), "%s", s);
606 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
609 itmp = newSymbol (buffer, 1);
610 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
616 /*-----------------------------------------------------------------*/
617 /* newiTempLabel - creates a temp variable label */
618 /*-----------------------------------------------------------------*/
620 newiTempLabel (char *s)
624 /* check if this already exists */
625 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
630 itmplbl = newSymbol (s, 1);
634 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
635 itmplbl = newSymbol (buffer, 1);
640 itmplbl->key = labelKey++;
641 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
645 /*-----------------------------------------------------------------*/
646 /* newiTempLoopHeaderLabel - creates a new loop header label */
647 /*-----------------------------------------------------------------*/
649 newiTempLoopHeaderLabel (bool pre)
653 SNPRINTF (buffer, sizeof(buffer), pre ? "preHeaderLbl%d" : LOOPEXITLBL "%d",
655 itmplbl = newSymbol (buffer, 1);
659 itmplbl->key = labelKey++;
660 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
665 /*-----------------------------------------------------------------*/
666 /* initiCode - initialises some iCode related stuff */
667 /*-----------------------------------------------------------------*/
674 /*-----------------------------------------------------------------*/
675 /* copyiCode - make a copy of the iCode given */
676 /*-----------------------------------------------------------------*/
678 copyiCode (iCode * ic)
680 iCode *nic = newiCode (ic->op, NULL, NULL);
682 nic->lineno = ic->lineno;
683 nic->filename = ic->filename;
684 nic->block = ic->block;
685 nic->level = ic->level;
686 nic->parmBytes = ic->parmBytes;
688 /* deal with the special cases first */
692 IC_COND (nic) = operandFromOperand (IC_COND (ic));
693 IC_TRUE (nic) = IC_TRUE (ic);
694 IC_FALSE (nic) = IC_FALSE (ic);
698 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
699 IC_JTLABELS (nic) = IC_JTLABELS (ic);
704 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
705 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
709 IC_INLINE (nic) = IC_INLINE (ic);
713 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
717 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
718 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
719 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
725 /*-----------------------------------------------------------------*/
726 /* getTableEntry - gets the table entry for the given operator */
727 /*-----------------------------------------------------------------*/
729 getTableEntry (int oper)
733 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
734 if (oper == codeTable[i].icode)
735 return &codeTable[i];
740 /*-----------------------------------------------------------------*/
741 /* newiTempOperand - new intermediate temp operand */
742 /*-----------------------------------------------------------------*/
744 newiTempOperand (sym_link * type, char throwType)
747 operand *op = newOperand ();
751 itmp = newiTemp (NULL);
753 etype = getSpec (type);
755 if (IS_LITERAL (etype))
758 /* copy the type information */
760 itmp->etype = getSpec (itmp->type = (throwType ? type :
761 copyLinkChain (type)));
762 if (IS_LITERAL (itmp->etype))
764 SPEC_SCLS (itmp->etype) = S_REGISTER;
765 SPEC_OCLS (itmp->etype) = reg;
768 op->operand.symOperand = itmp;
769 op->key = itmp->key = ++operandKey;
773 /*-----------------------------------------------------------------*/
774 /* operandType - returns the type chain for an operand */
775 /*-----------------------------------------------------------------*/
777 operandType (operand * op)
779 /* depending on type of operand */
784 return op->operand.valOperand->type;
787 return op->operand.symOperand->type;
790 return op->operand.typeOperand;
792 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
793 " operand type not known ");
794 assert (0); /* should never come here */
795 /* Just to keep the compiler happy */
796 return (sym_link *) 0;
800 /*-----------------------------------------------------------------*/
801 /* isParamterToCall - will return 1 if op is a parameter to args */
802 /*-----------------------------------------------------------------*/
804 isParameterToCall (value * args, operand * op)
808 wassert (IS_SYMOP(op));
813 isSymbolEqual (op->operand.symOperand, tval->sym))
820 /*-----------------------------------------------------------------*/
821 /* isOperandGlobal - return 1 if operand is a global variable */
822 /*-----------------------------------------------------------------*/
824 isOperandGlobal (operand * op)
833 (op->operand.symOperand->level == 0 ||
834 IS_STATIC (op->operand.symOperand->etype) ||
835 IS_EXTERN (op->operand.symOperand->etype))
842 /*-----------------------------------------------------------------*/
843 /* isOperandVolatile - return 1 if the operand is volatile */
844 /*-----------------------------------------------------------------*/
846 isOperandVolatile (operand * op, bool chkTemp)
851 if (IS_ITEMP (op) && !chkTemp)
854 opetype = getSpec (optype = operandType (op));
856 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
859 if (IS_VOLATILE (opetype))
864 /*-----------------------------------------------------------------*/
865 /* isOperandLiteral - returns 1 if an operand contains a literal */
866 /*-----------------------------------------------------------------*/
868 isOperandLiteral (operand * op)
875 opetype = getSpec (operandType (op));
877 if (IS_LITERAL (opetype))
883 /*-----------------------------------------------------------------*/
884 /* isOperandInFarSpace - will return true if operand is in farSpace */
885 /*-----------------------------------------------------------------*/
887 isOperandInFarSpace (operand * op)
897 if (!IS_TRUE_SYMOP (op))
900 etype = SPIL_LOC (op)->etype;
906 etype = getSpec (operandType (op));
908 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
911 /*-----------------------------------------------------------------*/
912 /* isOperandInPagedSpace - return true if operand is in pagedSpace */
913 /*-----------------------------------------------------------------*/
915 isOperandInPagedSpace (operand * op)
925 if (!IS_TRUE_SYMOP (op))
928 etype = SPIL_LOC (op)->etype;
934 etype = getSpec (operandType (op));
936 return (IN_PAGEDSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
939 /*------------------------------------------------------------------*/
940 /* isOperandInDirSpace - will return true if operand is in dirSpace */
941 /*------------------------------------------------------------------*/
943 isOperandInDirSpace (operand * op)
953 if (!IS_TRUE_SYMOP (op))
956 etype = SPIL_LOC (op)->etype;
962 etype = getSpec (operandType (op));
964 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
967 /*--------------------------------------------------------------------*/
968 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
969 /*--------------------------------------------------------------------*/
971 isOperandInCodeSpace (operand * op)
981 etype = getSpec (operandType (op));
983 if (!IS_TRUE_SYMOP (op))
986 etype = SPIL_LOC (op)->etype;
992 etype = getSpec (operandType (op));
994 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
997 /*-----------------------------------------------------------------*/
998 /* isOperandOnStack - will return true if operand is on stack */
999 /*-----------------------------------------------------------------*/
1001 isOperandOnStack (operand * op)
1011 etype = getSpec (operandType (op));
1012 if (IN_STACK (etype) ||
1013 OP_SYMBOL(op)->onStack ||
1014 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1020 /*-----------------------------------------------------------------*/
1021 /* isOclsExpensive - will return true if accesses to an output */
1022 /* storage class are expensive */
1023 /*-----------------------------------------------------------------*/
1025 isOclsExpensive (struct memmap *oclass)
1027 if (port->oclsExpense)
1028 return port->oclsExpense (oclass) > 0;
1030 /* In the absence of port specific guidance, assume only */
1031 /* farspace is expensive. */
1032 return IN_FARSPACE (oclass);
1035 /*-----------------------------------------------------------------*/
1036 /* isiCodeInFunctionCall - return TRUE if an iCode is between a */
1037 /* CALL/PCALL and the first IPUSH/SEND associated with the call */
1038 /*-----------------------------------------------------------------*/
1040 isiCodeInFunctionCall (iCode * ic)
1044 /* Find the next CALL/PCALL */
1047 if (lic->op == CALL || lic->op == PCALL)
1055 /* A function call was found. Scan backwards and see if an */
1056 /* IPUSH or SEND is encountered */
1059 if (lic != ic && (ic->op == CALL || ic->op == PCALL))
1061 if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
1069 /*-----------------------------------------------------------------*/
1070 /* operandLitValue - literal value of an operand */
1071 /*-----------------------------------------------------------------*/
1073 operandLitValue (operand * op)
1075 assert (isOperandLiteral (op));
1077 return floatFromVal (op->operand.valOperand);
1080 /*-----------------------------------------------------------------*/
1081 /* getBuiltInParms - returns parameters to a builtin functions */
1082 /*-----------------------------------------------------------------*/
1083 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1088 /* builtin functions uses only SEND for parameters */
1089 while (ic->op != CALL) {
1090 assert(ic->op == SEND && ic->builtinSEND);
1091 ic->generated = 1; /* mark the icode as generated */
1092 parms[*pcount] = IC_LEFT(ic);
1098 /* make sure this is a builtin function call */
1099 assert(IS_SYMOP(IC_LEFT(ic)));
1100 ftype = operandType(IC_LEFT(ic));
1101 assert(IFFUNC_ISBUILTIN(ftype));
1105 /*-----------------------------------------------------------------*/
1106 /* operandOperation - performs operations on operands */
1107 /*-----------------------------------------------------------------*/
1109 operandOperation (operand * left, operand * right,
1110 int op, sym_link * type)
1112 sym_link *let , *ret=NULL;
1113 operand *retval = (operand *) 0;
1115 assert (isOperandLiteral (left));
1116 let = getSpec(operandType(left));
1118 assert (isOperandLiteral (right));
1119 ret = getSpec(operandType(right));
1125 retval = operandFromValue (valCastLiteral (type,
1126 operandLitValue (left) +
1127 operandLitValue (right)));
1130 retval = operandFromValue (valCastLiteral (type,
1131 operandLitValue (left) -
1132 operandLitValue (right)));
1136 retval = operandFromValue (valCastLiteral (type,
1137 operandLitValue (left) *
1138 operandLitValue (right)));
1139 This could be all we've to do, but with gcc we've to take care about
1140 overflows. Two examples:
1141 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1142 significant bits are lost (52 in fraction, 63 bits would be
1143 necessary to keep full precision).
1144 If the resulting double value is greater than ULONG_MAX (resp.
1145 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1148 /* if it is not a specifier then we can assume that */
1149 /* it will be an unsigned long */
1150 if (IS_INT (type) ||
1153 /* long is handled here, because it can overflow with double */
1154 if (IS_LONG (type) ||
1156 /* signed and unsigned mul are the same, as long as the precision
1157 of the result isn't bigger than the precision of the operands. */
1158 retval = operandFromValue (valCastLiteral (type,
1159 (TYPE_TARGET_ULONG) operandLitValue (left) *
1160 (TYPE_TARGET_ULONG) operandLitValue (right)));
1161 else if (IS_UNSIGNED (type)) /* unsigned int */
1163 /* unsigned int is handled here in order to detect overflow */
1164 TYPE_TARGET_ULONG ul = (TYPE_TARGET_UINT) operandLitValue (left) *
1165 (TYPE_TARGET_UINT) operandLitValue (right);
1167 retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_UINT) ul));
1168 if (ul != (TYPE_TARGET_UINT) ul)
1171 else /* signed int */
1173 /* signed int is handled here in order to detect overflow */
1174 TYPE_TARGET_LONG l = (TYPE_TARGET_INT) operandLitValue (left) *
1175 (TYPE_TARGET_INT) operandLitValue (right);
1177 retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_INT) l));
1178 if (l != (TYPE_TARGET_INT) l)
1183 /* all others go here: */
1184 retval = operandFromValue (valCastLiteral (type,
1185 operandLitValue (left) *
1186 operandLitValue (right)));
1189 if ((TYPE_TARGET_ULONG) operandLitValue (right) == 0)
1191 werror (E_DIVIDE_BY_ZERO);
1197 if (IS_UNSIGNED (type))
1199 SPEC_USIGN (let) = 1;
1200 SPEC_USIGN (ret) = 1;
1201 retval = operandFromValue (valCastLiteral (type,
1202 (TYPE_TARGET_ULONG) operandLitValue (left) /
1203 (TYPE_TARGET_ULONG) operandLitValue (right)));
1207 retval = operandFromValue (valCastLiteral (type,
1208 operandLitValue (left) /
1209 operandLitValue (right)));
1214 if ((TYPE_TARGET_ULONG) operandLitValue (right) == 0)
1216 werror (E_DIVIDE_BY_ZERO);
1221 if (IS_UNSIGNED (type))
1222 retval = operandFromLit ((TYPE_TARGET_ULONG) operandLitValue (left) %
1223 (TYPE_TARGET_ULONG) operandLitValue (right));
1225 retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) %
1226 (TYPE_TARGET_LONG) operandLitValue (right));
1230 /* The number of left shifts is always unsigned. Signed doesn't make
1231 sense here. Shifting by a negative number is impossible. */
1232 retval = operandFromValue (valCastLiteral (type,
1233 ((TYPE_TARGET_ULONG) operandLitValue (left) <<
1234 (TYPE_TARGET_ULONG) operandLitValue (right))));
1237 /* The number of right shifts is always unsigned. Signed doesn't make
1238 sense here. Shifting by a negative number is impossible. */
1239 if (IS_UNSIGNED(let))
1240 /* unsigned: logic shift right */
1241 retval = operandFromLit ((TYPE_TARGET_ULONG) operandLitValue (left) >>
1242 (TYPE_TARGET_ULONG) operandLitValue (right));
1244 /* signed: arithmetic shift right */
1245 retval = operandFromLit ((TYPE_TARGET_LONG ) operandLitValue (left) >>
1246 (TYPE_TARGET_ULONG) operandLitValue (right));
1249 if (IS_FLOAT (let) || IS_FLOAT (ret))
1251 retval = operandFromLit (operandLitValue (left) ==
1252 operandLitValue (right));
1254 else if (IS_FIXED16X16 (let) || IS_FIXED16X16 (ret))
1256 retval = operandFromLit (operandLitValue (left) ==
1257 operandLitValue (right));
1261 /* this op doesn't care about signedness */
1262 TYPE_TARGET_ULONG l, r;
1264 l = (TYPE_TARGET_ULONG) operandLitValue (left);
1265 r = (TYPE_TARGET_ULONG) operandLitValue (right);
1266 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1267 neccessary to strip them to 16 bit.
1268 Literals are reduced to their cheapest type, therefore left and
1269 right might have different types. It's neccessary to find a
1270 common type: int (used for char too) or long */
1271 if (!IS_LONG (let) &&
1274 r = (TYPE_TARGET_UINT) r;
1275 l = (TYPE_TARGET_UINT) l;
1277 retval = operandFromLit (l == r);
1281 retval = operandFromLit (operandLitValue (left) <
1282 operandLitValue (right));
1285 retval = operandFromLit (operandLitValue (left) <=
1286 operandLitValue (right));
1289 retval = operandFromLit (operandLitValue (left) !=
1290 operandLitValue (right));
1293 retval = operandFromLit (operandLitValue (left) >
1294 operandLitValue (right));
1297 retval = operandFromLit (operandLitValue (left) >=
1298 operandLitValue (right));
1301 retval = operandFromValue (valCastLiteral (type,
1302 (TYPE_TARGET_ULONG)operandLitValue(left) &
1303 (TYPE_TARGET_ULONG)operandLitValue(right)));
1306 retval = operandFromValue (valCastLiteral (type,
1307 (TYPE_TARGET_ULONG)operandLitValue(left) |
1308 (TYPE_TARGET_ULONG)operandLitValue(right)));
1311 retval = operandFromValue (valCastLiteral (type,
1312 (TYPE_TARGET_ULONG)operandLitValue(left) ^
1313 (TYPE_TARGET_ULONG)operandLitValue(right)));
1316 retval = operandFromLit (operandLitValue (left) &&
1317 operandLitValue (right));
1320 retval = operandFromLit (operandLitValue (left) ||
1321 operandLitValue (right));
1325 TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) operandLitValue (left);
1327 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1333 TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) operandLitValue (left);
1335 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1340 retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1341 (TYPE_TARGET_ULONG)operandLitValue(right)) & 1);
1344 retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1345 (TYPE_TARGET_ULONG)operandLitValue(right)) & 0xFF);
1348 retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1349 (TYPE_TARGET_ULONG)operandLitValue(right)) & 0xFFFF);
1353 retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1354 ((getSize (let) * 8) - 1)) & 1);
1358 retval = operandFromValue (valCastLiteral (type,
1359 -1 * operandLitValue (left)));
1363 retval = operandFromValue (valCastLiteral (type,
1364 ~((TYPE_TARGET_ULONG)
1365 operandLitValue (left))));
1369 retval = operandFromLit (!operandLitValue (left));
1373 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1374 " operandOperation invalid operator ");
1382 /*-----------------------------------------------------------------*/
1383 /* isOperandEqual - compares two operand & return 1 if they r = */
1384 /*-----------------------------------------------------------------*/
1386 isOperandEqual (operand * left, operand * right)
1388 /* if the pointers are equal then they are equal */
1392 /* if either of them null then false */
1393 if (!left || !right)
1396 if (left->type != right->type)
1399 if (IS_SYMOP (left) && IS_SYMOP (right))
1400 return left->key == right->key;
1402 /* if types are the same */
1406 return isSymbolEqual (left->operand.symOperand,
1407 right->operand.symOperand);
1409 return (compareType (left->operand.valOperand->type,
1410 right->operand.valOperand->type) &&
1411 (floatFromVal (left->operand.valOperand) ==
1412 floatFromVal (right->operand.valOperand)));
1414 if (compareType (left->operand.typeOperand,
1415 right->operand.typeOperand) == 1)
1422 /*-------------------------------------------------------------------*/
1423 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1424 /*-------------------------------------------------------------------*/
1426 isiCodeEqual (iCode * left, iCode * right)
1428 /* if the same pointer */
1432 /* if either of them null */
1433 if (!left || !right)
1436 /* if operand are the same */
1437 if (left->op == right->op)
1440 /* compare all the elements depending on type */
1441 if (left->op != IFX)
1443 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1445 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1451 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1453 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1455 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1464 /*-----------------------------------------------------------------*/
1465 /* newiTempFromOp - create a temp Operand with same attributes */
1466 /*-----------------------------------------------------------------*/
1468 newiTempFromOp (operand * op)
1478 nop = newiTempOperand (operandType (op), TRUE);
1479 nop->isaddr = op->isaddr;
1480 nop->isvolatile = op->isvolatile;
1481 nop->isGlobal = op->isGlobal;
1482 nop->isLiteral = op->isLiteral;
1483 nop->usesDefs = op->usesDefs;
1484 nop->isParm = op->isParm;
1488 /*-----------------------------------------------------------------*/
1489 /* operand from operand - creates an operand holder for the type */
1490 /*-----------------------------------------------------------------*/
1492 operandFromOperand (operand * op)
1498 nop = newOperand ();
1499 nop->type = op->type;
1500 nop->isaddr = op->isaddr;
1502 nop->isvolatile = op->isvolatile;
1503 nop->isGlobal = op->isGlobal;
1504 nop->isLiteral = op->isLiteral;
1505 nop->usesDefs = op->usesDefs;
1506 nop->isParm = op->isParm;
1511 nop->operand.symOperand = op->operand.symOperand;
1514 nop->operand.valOperand = op->operand.valOperand;
1517 nop->operand.typeOperand = op->operand.typeOperand;
1524 /*-----------------------------------------------------------------*/
1525 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1526 /*-----------------------------------------------------------------*/
1528 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1530 operand *nop = operandFromOperand (op);
1532 if (nop->type == SYMBOL)
1534 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1535 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1541 /*-----------------------------------------------------------------*/
1542 /* operandFromSymbol - creates an operand from a symbol */
1543 /*-----------------------------------------------------------------*/
1545 operandFromSymbol (symbol * sym)
1550 /* if the symbol's type is a literal */
1551 /* then it is an enumerator type */
1552 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1553 return operandFromValue (valFromType (sym->etype));
1556 sym->key = ++operandKey;
1558 /* if this an implicit variable, means struct/union */
1559 /* member so just return it */
1560 if (sym->implicit || IS_FUNC (sym->type))
1564 op->operand.symOperand = sym;
1566 op->isvolatile = isOperandVolatile (op, TRUE);
1567 op->isGlobal = isOperandGlobal (op);
1571 /* under the following conditions create a
1572 register equivalent for a local symbol */
1573 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1574 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1576 (!(options.model == MODEL_FLAT24)) ) &&
1577 options.stackAuto == 0)
1580 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1581 !IS_FUNC (sym->type) && /* not a function */
1582 !sym->_isparm && /* not a parameter */
1583 IS_AUTO (sym) && /* is a local auto variable */
1584 !sym->addrtaken && /* whose address has not been taken */
1585 !sym->reqv && /* does not already have a reg equivalence */
1586 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1587 !sym->islbl && /* not a label */
1588 ok /* farspace check */
1592 /* we will use it after all optimizations
1593 and before liveRange calculation */
1594 sym->reqv = newiTempOperand (sym->type, 0);
1595 sym->reqv->key = sym->key;
1596 OP_SYMBOL (sym->reqv)->prereqv = sym;
1597 OP_SYMBOL (sym->reqv)->key = sym->key;
1598 OP_SYMBOL (sym->reqv)->isreqv = 1;
1599 OP_SYMBOL (sym->reqv)->islocal = 1;
1600 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1601 SPIL_LOC (sym->reqv) = sym;
1604 if (!IS_AGGREGATE (sym->type))
1608 op->operand.symOperand = sym;
1611 op->isvolatile = isOperandVolatile (op, TRUE);
1612 op->isGlobal = isOperandGlobal (op);
1613 op->isPtr = IS_PTR (operandType (op));
1614 op->isParm = sym->_isparm;
1619 /* itemp = &[_symbol] */
1621 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1622 IC_LEFT (ic)->type = SYMBOL;
1623 IC_LEFT (ic)->operand.symOperand = sym;
1624 IC_LEFT (ic)->key = sym->key;
1625 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1626 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1627 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1630 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1631 if (IS_ARRAY (sym->type))
1633 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1634 IC_RESULT (ic)->isaddr = 0;
1637 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1641 return IC_RESULT (ic);
1644 /*-----------------------------------------------------------------*/
1645 /* operandFromValue - creates an operand from value */
1646 /*-----------------------------------------------------------------*/
1648 operandFromValue (value * val)
1652 /* if this is a symbol then do the symbol thing */
1654 return operandFromSymbol (val->sym);
1656 /* this is not a symbol */
1659 op->operand.valOperand = val;
1660 op->isLiteral = isOperandLiteral (op);
1664 /*-----------------------------------------------------------------*/
1665 /* operandFromLink - operand from typeChain */
1666 /*-----------------------------------------------------------------*/
1668 operandFromLink (sym_link * type)
1672 /* operand from sym_link */
1678 op->operand.typeOperand = copyLinkChain (type);
1682 /*-----------------------------------------------------------------*/
1683 /* operandFromLit - makes an operand from a literal value */
1684 /*-----------------------------------------------------------------*/
1686 operandFromLit (double i)
1688 return operandFromValue (valueFromLit (i));
1691 /*-----------------------------------------------------------------*/
1692 /* operandFromAst - creates an operand from an ast */
1693 /*-----------------------------------------------------------------*/
1695 operandFromAst (ast * tree,int lvl)
1701 /* depending on type do */
1705 return ast2iCode (tree,lvl+1);
1709 return operandFromValue (tree->opval.val);
1713 return operandFromLink (tree->opval.lnk);
1720 /* Just to keep the compiler happy */
1721 return (operand *) 0;
1724 /*-----------------------------------------------------------------*/
1725 /* setOperandType - sets the operand's type to the given type */
1726 /*-----------------------------------------------------------------*/
1728 setOperandType (operand * op, sym_link * type)
1730 /* depending on the type of operand */
1735 op->operand.valOperand->etype =
1736 getSpec (op->operand.valOperand->type =
1737 copyLinkChain (type));
1741 if (op->operand.symOperand->isitmp)
1742 op->operand.symOperand->etype =
1743 getSpec (op->operand.symOperand->type =
1744 copyLinkChain (type));
1746 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1747 "attempt to modify type of source");
1751 op->operand.typeOperand = copyLinkChain (type);
1757 /*-----------------------------------------------------------------*/
1758 /* Get size in byte of ptr need to access an array */
1759 /*-----------------------------------------------------------------*/
1761 getArraySizePtr (operand * op)
1763 sym_link *ltype = operandType(op);
1767 int size = getSize(ltype);
1768 return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1773 sym_link *letype = getSpec(ltype);
1774 switch (PTR_TYPE (SPEC_OCLS (letype)))
1786 if (GPTRSIZE > FPTRSIZE)
1787 return (GPTRSIZE-1);
1798 /*-----------------------------------------------------------------*/
1799 /* perform "usual unary conversions" */
1800 /*-----------------------------------------------------------------*/
1803 usualUnaryConversions (operand * op)
1805 if (IS_INTEGRAL (operandType (op)))
1807 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1810 return geniCodeCast (INTTYPE, op, TRUE);
1817 /*-----------------------------------------------------------------*/
1818 /* perform "usual binary conversions" */
1819 /*-----------------------------------------------------------------*/
1822 usualBinaryConversions (operand ** op1, operand ** op2,
1823 RESULT_TYPE resultType, int op)
1826 sym_link *rtype = operandType (*op2);
1827 sym_link *ltype = operandType (*op1);
1829 ctype = computeType (ltype, rtype, resultType, op);
1836 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1838 /* one byte operations: keep signedness for code generator */
1846 *op1 = geniCodeCast (ctype, *op1, TRUE);
1847 *op2 = geniCodeCast (ctype, *op2, TRUE);
1852 /*-----------------------------------------------------------------*/
1853 /* geniCodeValueAtAddress - generate intermeditate code for value */
1855 /*-----------------------------------------------------------------*/
1857 geniCodeRValue (operand * op, bool force)
1860 sym_link *type = operandType (op);
1861 sym_link *etype = getSpec (type);
1863 /* if this is an array & already */
1864 /* an address then return this */
1865 if (IS_AGGREGATE (type) ||
1866 (IS_PTR (type) && !force && !op->isaddr))
1867 return operandFromOperand (op);
1869 /* if this is not an address then must be */
1870 /* rvalue already so return this one */
1874 /* if this is not a temp symbol then */
1875 if (!IS_ITEMP (op) &&
1877 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1879 op = operandFromOperand (op);
1884 if (IS_SPEC (type) &&
1885 IS_TRUE_SYMOP (op) &&
1886 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1887 (options.model == MODEL_FLAT24) ))
1889 op = operandFromOperand (op);
1894 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1895 if (IS_PTR (type) && op->isaddr && force)
1898 type = copyLinkChain (type);
1900 IC_RESULT (ic) = newiTempOperand (type, 1);
1901 IC_RESULT (ic)->isaddr = 0;
1903 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1907 return IC_RESULT (ic);
1910 /*-----------------------------------------------------------------*/
1911 /* geniCodeCast - changes the value from one type to another */
1912 /*-----------------------------------------------------------------*/
1914 geniCodeCast (sym_link * type, operand * op, bool implicit)
1918 sym_link *opetype = getSpec (optype = operandType (op));
1922 /* one of them has size zero then error */
1923 if (IS_VOID (optype))
1925 werror (E_CAST_ZERO);
1929 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1931 geniCodeArray2Ptr (op);
1935 /* if the operand is already the desired type then do nothing */
1936 if (compareType (type, optype) == 1)
1939 /* if this is a literal then just change the type & return */
1940 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1942 return operandFromValue (valCastLiteral (type,
1943 operandLitValue (op)));
1946 /* if casting to/from pointers, do some checking */
1947 if (IS_PTR(type)) { // to a pointer
1948 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1949 if (IS_INTEGRAL(optype)) {
1950 // maybe this is NULL, than it's ok.
1951 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1952 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1953 // no way to set the storage
1954 if (IS_LITERAL(optype)) {
1955 werror(E_LITERAL_GENERIC);
1958 werror(E_NONPTR2_GENPTR);
1961 } else if (implicit) {
1962 werror(W_INTEGRAL2PTR_NOCAST);
1967 // shouldn't do that with float, array or structure unless to void
1968 if (!IS_VOID(getSpec(type)) &&
1969 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1970 werror(E_INCOMPAT_TYPES);
1974 } else { // from a pointer to a pointer
1975 if (IS_GENPTR(type) && IS_VOID(type->next))
1976 { // cast to void* is always allowed
1978 else if (IS_GENPTR(optype) && IS_VOID(optype->next))
1979 { // cast from void* is always allowed
1981 else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
1982 // if not a pointer to a function
1983 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1984 if (implicit) { // if not to generic, they have to match
1985 if (!IS_GENPTR(type) &&
1986 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
1987 ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
1991 werror(E_INCOMPAT_PTYPES);
1998 } else { // to a non pointer
1999 if (IS_PTR(optype)) { // from a pointer
2000 if (implicit) { // sneaky
2001 if (IS_INTEGRAL(type)) {
2002 werror(W_PTR2INTEGRAL_NOCAST);
2004 } else { // shouldn't do that with float, array or structure
2005 werror(E_INCOMPAT_TYPES);
2012 printFromToType (optype, type);
2015 /* if they are the same size create an assignment */
2017 /* This seems very dangerous to me, since there are several */
2018 /* optimizations (for example, gcse) that don't notice the */
2019 /* cast hidden in this assignement and may simplify an */
2020 /* iCode to use the original (uncasted) operand. */
2021 /* Unfortunately, other things break when this cast is */
2022 /* made explicit. Need to fix this someday. */
2023 /* -- EEP, 2004/01/21 */
2024 if (getSize (type) == getSize (optype) &&
2025 !IS_BITFIELD (type) &&
2027 !IS_FLOAT (optype) &&
2029 !IS_FIXED (optype) &&
2030 ((IS_SPEC (type) && IS_SPEC (optype)) ||
2031 (!IS_SPEC (type) && !IS_SPEC (optype))))
2033 ic = newiCode ('=', NULL, op);
2034 IC_RESULT (ic) = newiTempOperand (type, 0);
2035 if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
2036 SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
2037 IC_RESULT (ic)->isaddr = 0;
2041 ic = newiCode (CAST, operandFromLink (type),
2042 geniCodeRValue (op, FALSE));
2044 IC_RESULT (ic) = newiTempOperand (type, 0);
2047 /* preserve the storage class & output class */
2048 /* of the original variable */
2049 restype = getSpec (operandType (IC_RESULT (ic)));
2050 if (!IS_LITERAL(opetype) &&
2053 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2054 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2057 return IC_RESULT (ic);
2060 /*-----------------------------------------------------------------*/
2061 /* geniCodeLabel - will create a Label */
2062 /*-----------------------------------------------------------------*/
2064 geniCodeLabel (symbol * label)
2068 ic = newiCodeLabelGoto (LABEL, label);
2072 /*-----------------------------------------------------------------*/
2073 /* geniCodeGoto - will create a Goto */
2074 /*-----------------------------------------------------------------*/
2076 geniCodeGoto (symbol * label)
2080 ic = newiCodeLabelGoto (GOTO, label);
2084 /*-----------------------------------------------------------------*/
2085 /* geniCodeMultiply - gen intermediate code for multiplication */
2086 /*-----------------------------------------------------------------*/
2088 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2095 /* if they are both literal then we know the result */
2096 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2097 return operandFromValue (valMult (left->operand.valOperand,
2098 right->operand.valOperand));
2100 if (IS_LITERAL(retype)) {
2101 p2 = powof2 ((TYPE_TARGET_ULONG) floatFromVal (right->operand.valOperand));
2104 resType = usualBinaryConversions (&left, &right, resultType, '*');
2106 rtype = operandType (right);
2107 retype = getSpec (rtype);
2108 ltype = operandType (left);
2109 letype = getSpec (ltype);
2112 /* if the right is a literal & power of 2 */
2113 /* then make it a left shift */
2114 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2115 efficient in most cases than 2 bytes result = 2 bytes << literal
2116 if port has 1 byte muldiv */
2117 if ((p2 > 0) && !IS_FLOAT (letype) && !IS_FIXED (letype)
2118 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2119 && (port->support.muldiv == 1))
2120 && strcmp (port->target, "pic16") != 0 /* don't shift for pic */
2121 && strcmp (port->target, "pic14") != 0)
2123 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2125 /* LEFT_OP need same size for left and result, */
2126 left = geniCodeCast (resType, left, TRUE);
2127 ltype = operandType (left);
2129 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2133 /* if the size left or right > 1 then support routine */
2134 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2136 if (IS_LITERAL (retype))
2137 ic = newiCode ('*', right, left); /* multiplication by support routine with one literal */
2139 ic = newiCode ('*', left, right); /* multiplication by support routine */
2144 ic = newiCode ('*', left, right); /* normal multiplication */
2147 IC_RESULT (ic) = newiTempOperand (resType, 1);
2150 return IC_RESULT (ic);
2153 /*-----------------------------------------------------------------*/
2154 /* geniCodeDivision - gen intermediate code for division */
2155 /*-----------------------------------------------------------------*/
2157 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2162 sym_link *rtype = operandType (right);
2163 sym_link *retype = getSpec (rtype);
2164 sym_link *ltype = operandType (left);
2165 sym_link *letype = getSpec (ltype);
2167 resType = usualBinaryConversions (&left, &right, resultType, '/');
2169 /* if the right is a literal & power of 2
2170 and left is unsigned then make it a
2172 if (IS_LITERAL (retype) &&
2173 !IS_FLOAT (letype) &&
2174 !IS_FIXED (letype) &&
2175 IS_UNSIGNED(letype) &&
2176 ((p2 = powof2 ((TYPE_TARGET_ULONG)
2177 floatFromVal (right->operand.valOperand))) > 0)) {
2178 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2182 ic = newiCode ('/', left, right); /* normal division */
2183 /* if the size left or right > 1 then support routine */
2184 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2187 IC_RESULT (ic) = newiTempOperand (resType, 0);
2190 return IC_RESULT (ic);
2192 /*-----------------------------------------------------------------*/
2193 /* geniCodeModulus - gen intermediate code for modulus */
2194 /*-----------------------------------------------------------------*/
2196 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2202 /* if they are both literal then we know the result */
2203 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2204 return operandFromValue (valMod (left->operand.valOperand,
2205 right->operand.valOperand));
2207 resType = usualBinaryConversions (&left, &right, resultType, '%');
2209 /* now they are the same size */
2210 ic = newiCode ('%', left, right);
2212 /* if the size left or right > 1 then support routine */
2213 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2215 IC_RESULT (ic) = newiTempOperand (resType, 0);
2218 return IC_RESULT (ic);
2221 /*-----------------------------------------------------------------*/
2222 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2223 /*-----------------------------------------------------------------*/
2225 geniCodePtrPtrSubtract (operand * left, operand * right)
2231 /* if they are both literals then */
2232 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2234 result = operandFromValue (valMinus (left->operand.valOperand,
2235 right->operand.valOperand));
2239 ic = newiCode ('-', left, right);
2241 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2245 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2249 // should we really do this? is this ANSI?
2250 return geniCodeDivision (result,
2251 operandFromLit (getSize (ltype->next)),
2255 /*-----------------------------------------------------------------*/
2256 /* geniCodeSubtract - generates code for subtraction */
2257 /*-----------------------------------------------------------------*/
2259 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2266 /* if they both pointers then */
2267 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2268 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2269 return geniCodePtrPtrSubtract (left, right);
2271 /* if they are both literal then we know the result */
2272 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2273 && left->isLiteral && right->isLiteral)
2274 return operandFromValue (valMinus (left->operand.valOperand,
2275 right->operand.valOperand));
2277 /* if left is an array or pointer */
2278 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2280 isarray = left->isaddr;
2281 right = geniCodeMultiply (right,
2282 operandFromLit (getSize (ltype->next)),
2283 (getArraySizePtr(left) >= INTSIZE) ?
2286 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2289 { /* make them the same size */
2290 resType = usualBinaryConversions (&left, &right, resultType, '-');
2293 ic = newiCode ('-', left, right);
2295 IC_RESULT (ic) = newiTempOperand (resType, 1);
2296 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2298 /* if left or right is a float */
2299 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2300 || IS_FIXED (ltype) || IS_FIXED (rtype))
2304 return IC_RESULT (ic);
2307 /*-----------------------------------------------------------------*/
2308 /* geniCodeAdd - generates iCode for addition */
2309 /*-----------------------------------------------------------------*/
2311 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2320 /* if the right side is LITERAL zero */
2321 /* return the left side */
2322 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2325 /* if left is literal zero return right */
2326 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2329 /* if left is a pointer then size */
2330 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2332 isarray = left->isaddr;
2333 // there is no need to multiply with 1
2334 if (getSize (ltype->next) != 1)
2336 size = operandFromLit (getSize (ltype->next));
2337 SPEC_USIGN (getSpec (operandType (size))) = 1;
2338 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2339 right = geniCodeMultiply (right, size, resultType);
2340 /* Even if right is a 'unsigned char',
2341 the result will be a 'signed int' due to the promotion rules.
2342 It doesn't make sense when accessing arrays, so let's fix it here: */
2344 SPEC_USIGN (getSpec (operandType (right))) = 1;
2346 resType = copyLinkChain (ltype);
2349 { // make them the same size
2350 resType = usualBinaryConversions (&left, &right, resultType, '+');
2353 /* if they are both literals then we know */
2354 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2355 && left->isLiteral && right->isLiteral)
2356 return operandFromValue (valPlus (valFromType (ltype),
2357 valFromType (rtype)));
2359 ic = newiCode ('+', left, right);
2361 IC_RESULT (ic) = newiTempOperand (resType, 1);
2362 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2364 /* if left or right is a float then support
2366 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2367 || IS_FIXED (ltype) || IS_FIXED (rtype))
2372 return IC_RESULT (ic);
2376 /*-----------------------------------------------------------------*/
2377 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2378 /*-----------------------------------------------------------------*/
2380 aggrToPtr (sym_link * type, bool force)
2385 if (IS_PTR (type) && !force)
2388 etype = getSpec (type);
2389 ptype = newLink (DECLARATOR);
2393 /* set the pointer depending on the storage class */
2394 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2398 /*------------------------------------------------------------------*/
2399 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2400 /*------------------------------------------------------------------*/
2402 aggrToPtrDclType (sym_link * type, bool force)
2404 if (IS_PTR (type) && !force)
2405 return DCL_TYPE (type);
2407 /* return the pointer depending on the storage class */
2408 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2411 /*-----------------------------------------------------------------*/
2412 /* geniCodeArray2Ptr - array to pointer */
2413 /*-----------------------------------------------------------------*/
2415 geniCodeArray2Ptr (operand * op)
2417 sym_link *optype = operandType (op);
2418 sym_link *opetype = getSpec (optype);
2420 /* set the pointer depending on the storage class */
2421 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2428 /*-----------------------------------------------------------------*/
2429 /* geniCodeArray - array access */
2430 /*-----------------------------------------------------------------*/
2432 geniCodeArray (operand * left, operand * right, int lvl)
2436 sym_link *ltype = operandType (left);
2438 RESULT_TYPE resultType;
2440 resultType = (getArraySizePtr(left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
2441 if (DCL_ELEM (ltype))
2443 if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
2444 resultType = RESULT_TYPE_CHAR;
2449 if (IS_PTR (ltype->next) && left->isaddr)
2451 left = geniCodeRValue (left, FALSE);
2454 return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl),
2457 size = operandFromLit (getSize (ltype->next));
2458 SPEC_USIGN (getSpec (operandType (size))) = 1;
2459 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2460 right = geniCodeMultiply (right, size, resultType);
2461 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2462 It doesn't make sense when accessing arrays, so let's fix it here: */
2464 SPEC_USIGN (getSpec (operandType (right))) = 1;
2465 /* we can check for limits here */
2466 /* already done in SDCCast.c
2467 if (isOperandLiteral (right) &&
2470 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2472 werror (W_IDX_OUT_OF_BOUNDS,
2473 (int) operandLitValue (right) / getSize (ltype->next),
2478 ic = newiCode ('+', left, right);
2480 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2481 !IS_AGGREGATE (ltype->next) &&
2482 !IS_PTR (ltype->next))
2483 ? ltype : ltype->next), 0);
2485 if (!IS_AGGREGATE (ltype->next))
2487 IC_RESULT (ic)->isaddr = 1;
2488 IC_RESULT (ic)->aggr2ptr = 1;
2492 return IC_RESULT (ic);
2495 /*-----------------------------------------------------------------*/
2496 /* geniCodeStruct - generates intermediate code for structures */
2497 /*-----------------------------------------------------------------*/
2499 geniCodeStruct (operand * left, operand * right, bool islval)
2502 sym_link *type = operandType (left);
2503 sym_link *etype = getSpec (type);
2505 symbol *element = getStructElement (SPEC_STRUCT (etype),
2506 right->operand.symOperand);
2508 wassert(IS_SYMOP(right));
2510 /* add the offset */
2511 ic = newiCode ('+', left, operandFromLit (element->offset));
2513 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2515 /* preserve the storage & output class of the struct */
2516 /* as well as the volatile attribute */
2517 retype = getSpec (operandType (IC_RESULT (ic)));
2518 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2519 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2520 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2521 SPEC_CONST (retype) |= SPEC_CONST (etype);
2523 if (IS_PTR (element->type))
2524 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2526 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2529 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2532 /*-----------------------------------------------------------------*/
2533 /* geniCodePostInc - generate int code for Post increment */
2534 /*-----------------------------------------------------------------*/
2536 geniCodePostInc (operand * op)
2540 sym_link *optype = operandType (op);
2542 operand *rv = (IS_ITEMP (op) ?
2543 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2545 sym_link *rvtype = operandType (rv);
2548 /* if this is not an address we have trouble */
2551 werror (E_LVALUE_REQUIRED, "++");
2555 rOp = newiTempOperand (rvtype, 0);
2556 OP_SYMBOL(rOp)->noSpilLoc = 1;
2559 OP_SYMBOL(rv)->noSpilLoc = 1;
2561 geniCodeAssign (rOp, rv, 0, 0);
2563 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2565 werror(W_SIZEOF_VOID);
2566 if (IS_FLOAT (rvtype))
2567 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2568 else if (IS_FIXED16X16 (rvtype))
2569 ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2571 ic = newiCode ('+', rv, operandFromLit (size));
2573 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2576 geniCodeAssign (op, result, 0, 0);
2582 /*-----------------------------------------------------------------*/
2583 /* geniCodePreInc - generate code for preIncrement */
2584 /*-----------------------------------------------------------------*/
2586 geniCodePreInc (operand * op, bool lvalue)
2589 sym_link *optype = operandType (op);
2590 operand *rop = (IS_ITEMP (op) ?
2591 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2593 sym_link *roptype = operandType (rop);
2599 werror (E_LVALUE_REQUIRED, "++");
2603 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2605 werror(W_SIZEOF_VOID);
2606 if (IS_FLOAT (roptype))
2607 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2608 else if (IS_FIXED16X16 (roptype))
2609 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2611 ic = newiCode ('+', rop, operandFromLit (size));
2612 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2615 (void) geniCodeAssign (op, result, 0, 0);
2616 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2622 /*-----------------------------------------------------------------*/
2623 /* geniCodePostDec - generates code for Post decrement */
2624 /*-----------------------------------------------------------------*/
2626 geniCodePostDec (operand * op)
2630 sym_link *optype = operandType (op);
2632 operand *rv = (IS_ITEMP (op) ?
2633 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2635 sym_link *rvtype = operandType (rv);
2638 /* if this is not an address we have trouble */
2641 werror (E_LVALUE_REQUIRED, "--");
2645 rOp = newiTempOperand (rvtype, 0);
2646 OP_SYMBOL(rOp)->noSpilLoc = 1;
2649 OP_SYMBOL(rv)->noSpilLoc = 1;
2651 geniCodeAssign (rOp, rv, 0, 0);
2653 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2655 werror(W_SIZEOF_VOID);
2656 if (IS_FLOAT (rvtype))
2657 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2658 else if (IS_FIXED16X16 (rvtype))
2659 ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2661 ic = newiCode ('-', rv, operandFromLit (size));
2663 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2666 geniCodeAssign (op, result, 0, 0);
2672 /*-----------------------------------------------------------------*/
2673 /* geniCodePreDec - generate code for pre decrement */
2674 /*-----------------------------------------------------------------*/
2676 geniCodePreDec (operand * op, bool lvalue)
2679 sym_link *optype = operandType (op);
2680 operand *rop = (IS_ITEMP (op) ?
2681 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2683 sym_link *roptype = operandType (rop);
2689 werror (E_LVALUE_REQUIRED, "--");
2693 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2695 werror(W_SIZEOF_VOID);
2696 if (IS_FLOAT (roptype))
2697 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2698 else if (IS_FIXED16X16 (roptype))
2699 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2701 ic = newiCode ('-', rop, operandFromLit (size));
2702 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2705 (void) geniCodeAssign (op, result, 0, 0);
2706 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2713 /*-----------------------------------------------------------------*/
2714 /* geniCodeBitwise - gen int code for bitWise operators */
2715 /*-----------------------------------------------------------------*/
2717 geniCodeBitwise (operand * left, operand * right,
2718 int oper, sym_link * resType)
2722 left = geniCodeCast (resType, left, TRUE);
2723 right = geniCodeCast (resType, right, TRUE);
2725 ic = newiCode (oper, left, right);
2726 IC_RESULT (ic) = newiTempOperand (resType, 0);
2729 return IC_RESULT (ic);
2732 /*-----------------------------------------------------------------*/
2733 /* geniCodeAddressOf - gens icode for '&' address of operator */
2734 /*-----------------------------------------------------------------*/
2736 geniCodeAddressOf (operand * op)
2740 sym_link *optype = operandType (op);
2741 sym_link *opetype = getSpec (optype);
2743 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2745 op = operandFromOperand (op);
2750 /* lvalue check already done in decorateType */
2751 /* this must be a lvalue */
2752 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2753 /* werror (E_LVALUE_REQUIRED,"&"); */
2757 p = newLink (DECLARATOR);
2759 /* set the pointer depending on the storage class */
2760 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2762 p->next = copyLinkChain (optype);
2764 /* if already a temp */
2767 setOperandType (op, p);
2772 /* otherwise make this of the type coming in */
2773 ic = newiCode (ADDRESS_OF, op, NULL);
2774 IC_RESULT (ic) = newiTempOperand (p, 1);
2775 IC_RESULT (ic)->isaddr = 0;
2777 return IC_RESULT (ic);
2780 /*-----------------------------------------------------------------*/
2781 /* setOClass - sets the output class depending on the pointer type */
2782 /*-----------------------------------------------------------------*/
2784 setOClass (sym_link * ptr, sym_link * spec)
2786 switch (DCL_TYPE (ptr))
2789 SPEC_OCLS (spec) = data;
2793 SPEC_OCLS (spec) = generic;
2797 SPEC_OCLS (spec) = xdata;
2801 SPEC_OCLS (spec) = code;
2805 SPEC_OCLS (spec) = idata;
2809 SPEC_OCLS (spec) = xstack;
2813 SPEC_OCLS (spec) = eeprom;
2822 /*-----------------------------------------------------------------*/
2823 /* geniCodeDerefPtr - dereference pointer with '*' */
2824 /*-----------------------------------------------------------------*/
2826 geniCodeDerefPtr (operand * op,int lvl)
2828 sym_link *rtype, *retype;
2829 sym_link *optype = operandType (op);
2831 // if this is an array then array access
2832 if (IS_ARRAY (optype)) {
2833 // don't worry, this will be optimized out later
2834 return geniCodeArray (op, operandFromLit (0), lvl);
2837 // just in case someone screws up
2838 wassert (IS_PTR (optype));
2840 if (IS_TRUE_SYMOP (op))
2843 op = geniCodeRValue (op, TRUE);
2846 /* now get rid of the pointer part */
2847 if (isLvaluereq(lvl) && IS_ITEMP (op))
2849 retype = getSpec (rtype = copyLinkChain (optype));
2853 retype = getSpec (rtype = copyLinkChain (optype->next));
2854 /* outputclass needs 2b updated */
2855 setOClass (optype, retype);
2858 op->isGptr = IS_GENPTR (optype);
2860 op->isaddr = (IS_PTR (rtype) ||
2861 IS_STRUCT (rtype) ||
2867 if (!isLvaluereq(lvl))
2868 op = geniCodeRValue (op, TRUE);
2870 setOperandType (op, rtype);
2875 /*-----------------------------------------------------------------*/
2876 /* geniCodeUnaryMinus - does a unary minus of the operand */
2877 /*-----------------------------------------------------------------*/
2879 geniCodeUnaryMinus (operand * op)
2882 sym_link *optype = operandType (op);
2884 if (IS_LITERAL (optype))
2885 return operandFromLit (-floatFromVal (op->operand.valOperand));
2887 ic = newiCode (UNARYMINUS, op, NULL);
2888 IC_RESULT (ic) = newiTempOperand (optype, 0);
2890 return IC_RESULT (ic);
2893 /*-----------------------------------------------------------------*/
2894 /* geniCodeLeftShift - gen i code for left shift */
2895 /*-----------------------------------------------------------------*/
2897 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2902 ic = newiCode (LEFT_OP, left, right);
2904 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2905 IC_RESULT (ic) = newiTempOperand (resType, 0);
2907 return IC_RESULT (ic);
2910 /*-----------------------------------------------------------------*/
2911 /* geniCodeRightShift - gen i code for right shift */
2912 /*-----------------------------------------------------------------*/
2914 geniCodeRightShift (operand * left, operand * right)
2918 ic = newiCode (RIGHT_OP, left, right);
2919 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2921 return IC_RESULT (ic);
2924 /*-----------------------------------------------------------------*/
2925 /* geniCodeLogic- logic code */
2926 /*-----------------------------------------------------------------*/
2928 geniCodeLogic (operand * left, operand * right, int op)
2932 sym_link *rtype = operandType (right);
2933 sym_link *ltype = operandType (left);
2935 /* left is integral type and right is literal then
2936 check if the literal value is within bounds */
2937 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2939 CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
2942 case CCR_ALWAYS_TRUE:
2943 case CCR_ALWAYS_FALSE:
2944 if (!options.lessPedantic)
2945 werror (W_COMP_RANGE, "true resp. false");
2946 return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
2952 /* if one operand is a pointer and the other is a literal generic void pointer,
2953 change the type of the literal generic void pointer to match the other pointer */
2954 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2955 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2957 /* find left's definition */
2958 ic = (iCode *) setFirstItem (iCodeChain);
2961 if (((ic->op == CAST) || (ic->op == '='))
2962 && isOperandEqual(left, IC_RESULT (ic)))
2965 ic = setNextItem (iCodeChain);
2967 /* if casting literal to generic pointer, then cast to rtype instead */
2968 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2970 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2971 ltype = operandType(left);
2974 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2975 && IS_PTR (ltype) && !IS_GENPTR(ltype))
2977 /* find right's definition */
2978 ic = (iCode *) setFirstItem (iCodeChain);
2981 if (((ic->op == CAST) || (ic->op == '='))
2982 && isOperandEqual(right, IC_RESULT (ic)))
2985 ic = setNextItem (iCodeChain);
2987 /* if casting literal to generic pointer, then cast to rtype instead */
2988 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2990 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2991 rtype = operandType(right);
2995 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_BIT, 0);
2997 ic = newiCode (op, left, right);
2998 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
3000 /* if comparing float
3001 and not a '==' || '!=' || '&&' || '||' (these
3003 if (IS_FLOAT(ctype) &&
3010 /* if comparing a fixed type use support functions */
3011 if (IS_FIXED(ctype))
3015 return IC_RESULT (ic);
3018 /*-----------------------------------------------------------------*/
3019 /* geniCodeLogicAndOr - && || operations */
3020 /*-----------------------------------------------------------------*/
3022 geniCodeLogicAndOr (ast *tree, int lvl)
3026 symbol *falseLabel = newiTempLabel (NULL);
3027 symbol *trueLabel = newiTempLabel (NULL);
3028 symbol *exitLabel = newiTempLabel (NULL);
3029 operand *op, *result, *condition;
3031 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3032 They can be reenabled by executing the following block. If you find
3033 a decent optimization you could start right here:
3038 operand *leftOp, *rightOp;
3040 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3041 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3043 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3047 /* generate two IFX for the '&&' or '||' op */
3049 /* evaluate left operand */
3050 condition = ast2iCode (tree->left, lvl + 1);
3051 op = geniCodeRValue (condition, FALSE);
3053 /* test left operand */
3054 if (tree->opval.op == AND_OP)
3055 ic = newiCodeCondition (op, NULL, falseLabel);
3057 ic = newiCodeCondition (op, trueLabel, NULL);
3060 /* evaluate right operand */
3061 condition = ast2iCode (tree->right, lvl + 1);
3062 op = geniCodeRValue (condition, FALSE);
3064 /* test right operand */
3065 ic = newiCodeCondition (op, trueLabel, NULL);
3068 /* store 0 or 1 in result */
3069 type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
3070 result = newiTempOperand (type, 1);
3072 geniCodeLabel (falseLabel);
3073 geniCodeAssign (result, operandFromLit (0), 0, 0);
3074 /* generate an unconditional goto */
3075 geniCodeGoto (exitLabel);
3077 geniCodeLabel (trueLabel);
3078 geniCodeAssign (result, operandFromLit (1), 0, 0);
3080 geniCodeLabel (exitLabel);
3085 /*-----------------------------------------------------------------*/
3086 /* geniCodeUnary - for a generic unary operation */
3087 /*-----------------------------------------------------------------*/
3089 geniCodeUnary (operand * op, int oper)
3091 iCode *ic = newiCode (oper, op, NULL);
3093 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3095 return IC_RESULT (ic);
3098 /*-----------------------------------------------------------------*/
3099 /* geniCodeBinary - for a generic binary operation */
3100 /*-----------------------------------------------------------------*/
3102 geniCodeBinary (operand * left, operand * right, int oper)
3104 iCode *ic = newiCode (oper, left, right);
3106 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3108 return IC_RESULT (ic);
3111 /*-----------------------------------------------------------------*/
3112 /* geniCodeConditional - geniCode for '?' ':' operation */
3113 /*-----------------------------------------------------------------*/
3115 geniCodeConditional (ast * tree,int lvl)
3118 symbol *falseLabel = newiTempLabel (NULL);
3119 symbol *exitLabel = newiTempLabel (NULL);
3120 operand *cond = ast2iCode (tree->left,lvl+1);
3121 operand *true, *false, *result;
3123 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3127 true = ast2iCode (tree->right->left,lvl+1);
3129 /* move the value to a new Operand */
3130 result = newiTempOperand (tree->right->ftype, 0);
3131 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3133 /* generate an unconditional goto */
3134 geniCodeGoto (exitLabel);
3136 /* now for the right side */
3137 geniCodeLabel (falseLabel);
3139 false = ast2iCode (tree->right->right,lvl+1);
3140 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3142 /* create the exit label */
3143 geniCodeLabel (exitLabel);
3148 /*-----------------------------------------------------------------*/
3149 /* geniCodeAssign - generate code for assignment */
3150 /*-----------------------------------------------------------------*/
3152 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3155 sym_link *ltype = operandType (left);
3156 sym_link *rtype = operandType (right);
3158 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3160 werror (E_LVALUE_REQUIRED, "assignment");
3164 /* left is integral type and right is literal then
3165 check if the literal value is within bounds */
3166 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
3167 checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL &&
3168 !options.lessPedantic)
3170 werror (W_LIT_OVERFLOW);
3173 /* if the left & right type don't exactly match */
3174 /* if pointer set then make sure the check is
3175 done with the type & not the pointer */
3176 /* then cast rights type to left */
3178 /* first check the type for pointer assignement */
3179 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3180 compareType (ltype, rtype) <= 0)
3182 if (compareType (ltype->next, rtype) < 0)
3183 right = geniCodeCast (ltype->next, right, TRUE);
3185 else if (compareType (ltype, rtype) < 0)
3186 right = geniCodeCast (ltype, right, TRUE);
3188 /* If left is a true symbol & ! volatile
3189 create an assignment to temporary for
3190 the right & then assign this temporary
3191 to the symbol. This is SSA (static single
3192 assignment). Isn't it simple and folks have
3193 published mountains of paper on it */
3194 if (IS_TRUE_SYMOP (left) &&
3195 !isOperandVolatile (left, FALSE) &&
3196 isOperandGlobal (left))
3201 if (IS_TRUE_SYMOP (right))
3202 sym = OP_SYMBOL (right);
3203 ic = newiCode ('=', NULL, right);
3204 IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
3205 /* avoid double fetch from volatile right, see bug 1369874 */
3206 if (!isOperandVolatile (right, FALSE))
3207 SPIL_LOC (newRight) = sym;
3212 ic = newiCode ('=', NULL, right);
3213 IC_RESULT (ic) = left;
3216 /* if left isgptr flag is set then support
3217 routine will be required */
3221 ic->nosupdate = nosupdate;
3225 /*-----------------------------------------------------------------*/
3226 /* geniCodeDummyRead - generate code for dummy read */
3227 /*-----------------------------------------------------------------*/
3229 geniCodeDummyRead (operand * op)
3232 sym_link *type = operandType (op);
3234 if (!IS_VOLATILE(type))
3237 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3243 /*-----------------------------------------------------------------*/
3244 /* geniCodeSEParms - generate code for side effecting fcalls */
3245 /*-----------------------------------------------------------------*/
3247 geniCodeSEParms (ast * parms,int lvl)
3252 if (parms->type == EX_OP && parms->opval.op == PARAM)
3254 geniCodeSEParms (parms->left,lvl);
3255 geniCodeSEParms (parms->right,lvl);
3259 /* hack don't like this but too lazy to think of
3261 if (IS_ADDRESS_OF_OP (parms))
3262 parms->left->lvalue = 1;
3264 if (IS_CAST_OP (parms) &&
3265 IS_PTR (parms->ftype) &&
3266 IS_ADDRESS_OF_OP (parms->right))
3267 parms->right->left->lvalue = 1;
3269 parms->opval.oprnd =
3270 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3272 parms->type = EX_OPERAND;
3273 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3274 SPEC_ARGREG(parms->ftype);
3277 /*-----------------------------------------------------------------*/
3278 /* geniCodeParms - generates parameters */
3279 /*-----------------------------------------------------------------*/
3281 geniCodeParms (ast * parms, value *argVals, int *stack,
3282 sym_link * ftype, int lvl)
3290 if (argVals==NULL) {
3292 argVals = FUNC_ARGS (ftype);
3295 /* if this is a param node then do the left & right */
3296 if (parms->type == EX_OP && parms->opval.op == PARAM)
3298 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3299 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3303 /* get the parameter value */
3304 if (parms->type == EX_OPERAND)
3305 pval = parms->opval.oprnd;
3308 /* maybe this else should go away ?? */
3309 /* hack don't like this but too lazy to think of
3311 if (IS_ADDRESS_OF_OP (parms))
3312 parms->left->lvalue = 1;
3314 if (IS_CAST_OP (parms) &&
3315 IS_PTR (parms->ftype) &&
3316 IS_ADDRESS_OF_OP (parms->right))
3317 parms->right->left->lvalue = 1;
3319 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3322 /* if register parm then make it a send */
3323 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3324 IFFUNC_ISBUILTIN(ftype))
3326 ic = newiCode (SEND, pval, NULL);
3327 ic->argreg = SPEC_ARGREG(parms->etype);
3328 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3333 /* now decide whether to push or assign */
3334 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3338 operand *top = operandFromSymbol (argVals->sym);
3339 /* clear useDef and other bitVectors */
3340 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3341 geniCodeAssign (top, pval, 1, 0);
3345 sym_link *p = operandType (pval);
3347 ic = newiCode (IPUSH, pval, NULL);
3349 /* update the stack adjustment */
3350 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3355 argVals=argVals->next;
3359 /*-----------------------------------------------------------------*/
3360 /* geniCodeCall - generates temp code for calling */
3361 /*-----------------------------------------------------------------*/
3363 geniCodeCall (operand * left, ast * parms,int lvl)
3367 sym_link *type, *etype;
3371 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3372 !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3373 werror (E_FUNCTION_EXPECTED);
3374 return operandFromValue(valueFromLit(0));
3377 /* take care of parameters with side-effecting
3378 function calls in them, this is required to take care
3379 of overlaying function parameters */
3380 geniCodeSEParms (parms,lvl);
3382 ftype = operandType (left);
3383 if (IS_FUNCPTR (ftype))
3384 ftype = ftype->next;
3386 /* first the parameters */
3387 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3389 /* now call : if symbol then pcall */
3390 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3391 ic = newiCode (PCALL, left, NULL);
3393 ic = newiCode (CALL, left, NULL);
3396 type = copyLinkChain (ftype->next);
3397 etype = getSpec (type);
3398 SPEC_EXTR (etype) = 0;
3399 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3403 /* stack adjustment after call */
3404 ic->parmBytes = stack;
3409 /*-----------------------------------------------------------------*/
3410 /* geniCodeReceive - generate intermediate code for "receive" */
3411 /*-----------------------------------------------------------------*/
3413 geniCodeReceive (value * args, operand * func)
3415 unsigned char paramByteCounter = 0;
3417 /* for all arguments that are passed in registers */
3420 if (IS_REGPARM (args->etype))
3422 operand *opr = operandFromValue (args);
3424 symbol *sym = OP_SYMBOL (opr);
3427 /* we will use it after all optimizations
3428 and before liveRange calculation */
3429 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3432 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3433 options.stackAuto == 0 &&
3434 (!(options.model == MODEL_FLAT24)) )
3439 opl = newiTempOperand (args->type, 0);
3441 sym->reqv->key = sym->key;
3442 OP_SYMBOL (sym->reqv)->key = sym->key;
3443 OP_SYMBOL (sym->reqv)->isreqv = 1;
3444 OP_SYMBOL (sym->reqv)->islocal = 0;
3445 SPIL_LOC (sym->reqv) = sym;
3449 ic = newiCode (RECEIVE, func, NULL);
3450 ic->argreg = SPEC_ARGREG(args->etype);
3451 if (ic->argreg == 1) {
3452 currFunc->recvSize = getSize (sym->type);
3454 IC_RESULT (ic) = opr;
3456 /* misuse of parmBytes (normally used for functions)
3457 * to save estimated stack position of this argument.
3458 * Normally this should be zero for RECEIVE iCodes.
3459 * No idea if this causes side effects on other ports. - dw
3461 ic->parmBytes = paramByteCounter;
3463 /* what stack position do we have? */
3464 paramByteCounter += getSize (sym->type);
3473 /*-----------------------------------------------------------------*/
3474 /* geniCodeFunctionBody - create the function body */
3475 /*-----------------------------------------------------------------*/
3477 geniCodeFunctionBody (ast * tree,int lvl)
3484 /* reset the auto generation */
3490 func = ast2iCode (tree->left,lvl+1);
3491 fetype = getSpec (operandType (func));
3493 savelineno = lineno;
3494 lineno = OP_SYMBOL (func)->lineDef;
3495 /* create an entry label */
3496 geniCodeLabel (entryLabel);
3497 lineno = savelineno;
3499 /* create a proc icode */
3500 ic = newiCode (FUNCTION, func, NULL);
3501 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3506 /* for all parameters that are passed
3507 on registers add a "receive" */
3508 geniCodeReceive (tree->values.args, func);
3510 /* generate code for the body */
3511 ast2iCode (tree->right,lvl+1);
3513 /* create a label for return */
3514 geniCodeLabel (returnLabel);
3516 /* now generate the end proc */
3517 ic = newiCode (ENDFUNCTION, func, NULL);
3523 /*-----------------------------------------------------------------*/
3524 /* geniCodeReturn - gen icode for 'return' statement */
3525 /*-----------------------------------------------------------------*/
3527 geniCodeReturn (operand * op)
3531 /* if the operand is present force an rvalue */
3533 op = geniCodeRValue (op, FALSE);
3535 ic = newiCode (RETURN, op, NULL);
3539 /*-----------------------------------------------------------------*/
3540 /* geniCodeIfx - generates code for extended if statement */
3541 /*-----------------------------------------------------------------*/
3543 geniCodeIfx (ast * tree,int lvl)
3546 operand *condition = ast2iCode (tree->left,lvl+1);
3549 /* if condition is null then exit */
3553 condition = geniCodeRValue (condition, FALSE);
3555 cetype = getSpec (operandType (condition));
3556 /* if the condition is a literal */
3557 if (IS_LITERAL (cetype))
3559 if (floatFromVal (condition->operand.valOperand))
3561 if (tree->trueLabel)
3562 geniCodeGoto (tree->trueLabel);
3568 if (tree->falseLabel)
3569 geniCodeGoto (tree->falseLabel);
3574 if (tree->trueLabel)
3576 ic = newiCodeCondition (condition,
3581 if (tree->falseLabel)
3582 geniCodeGoto (tree->falseLabel);
3586 ic = newiCodeCondition (condition,
3593 ast2iCode (tree->right,lvl+1);
3596 /*-----------------------------------------------------------------*/
3597 /* geniCodeJumpTable - tries to create a jump table for switch */
3598 /*-----------------------------------------------------------------*/
3600 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3602 int min, max, cnt = 1;
3609 int needRangeCheck = !optimize.noJTabBoundary
3610 || tree->values.switchVals.swDefault;
3611 sym_link *cetype = getSpec (operandType (cond));
3612 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3613 int sizeofMatchJump, sizeofJumpTable;
3616 if (!tree || !caseVals)
3619 /* the criteria for creating a jump table is */
3620 /* all integer numbers between the maximum & minimum must */
3621 /* be present , the maximum value should not exceed 255 */
3622 /* If not all integer numbers are present the algorithm */
3623 /* inserts jumps to the default label for the missing numbers */
3624 /* and decides later whether it is worth it */
3625 min = (int) floatFromVal (vch = caseVals);
3632 max = (int) floatFromVal (vch);
3634 /* Exit if the range is too large to handle with a jump table. */
3635 if (1 + max - min > port->jumptableCost.maxCount)
3638 switch (getSize (operandType (cond)))
3640 case 1: sizeIndex = 0; break;
3641 case 2: sizeIndex = 1; break;
3642 case 4: sizeIndex = 2; break;
3646 /* Compute the size cost of the range check and subtraction. */
3648 sizeofZeroMinCost = 0;
3652 if (!(min==0 && IS_UNSIGNED (cetype)))
3653 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3654 if (!IS_UNSIGNED (cetype))
3655 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3656 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3659 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3661 /* If the size cost of handling a non-zero minimum exceeds the */
3662 /* cost of extending the range down to zero, then it might be */
3663 /* better to extend the range to zero. */
3664 if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3665 >= (min * port->jumptableCost.sizeofElement))
3667 /* Only extend the jump table if it would still be manageable. */
3668 if (1 + max <= port->jumptableCost.maxCount)
3671 if (IS_UNSIGNED (cetype))
3674 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3678 /* Compute the total size cost of a jump table. */
3679 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3680 + port->jumptableCost.sizeofDispatch
3681 + sizeofMinCost + sizeofMaxCost;
3683 /* Compute the total size cost of a match & jump sequence */
3684 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3686 /* If the size cost of the jump table is uneconomical then exit */
3687 if (sizeofMatchJump < sizeofJumpTable)
3690 /* The jump table is preferable. */
3692 /* First, a label for the default or missing cases. */
3693 if (tree->values.switchVals.swDefault)
3695 SNPRINTF (buffer, sizeof(buffer),
3697 tree->values.switchVals.swNum);
3701 SNPRINTF (buffer, sizeof(buffer),
3703 tree->values.switchVals.swNum);
3705 falseLabel = newiTempLabel (buffer);
3707 /* Build the list of labels for the jump table. */
3709 t = (int) floatFromVal (vch);
3710 for (i=min; i<=max; i++)
3714 /* Explicit case: make a new label for it. */
3715 SNPRINTF (buffer, sizeof(buffer),
3717 tree->values.switchVals.swNum,
3719 addSet (&labels, newiTempLabel (buffer));
3722 t = (int) floatFromVal (vch);
3726 /* Implicit case: use the default label. */
3727 addSet (&labels, falseLabel);
3731 /* first we rule out the boundary conditions */
3732 /* if only optimization says so */
3735 sym_link *cetype = getSpec (operandType (cond));
3736 /* no need to check the lower bound if
3737 the condition is unsigned & minimum value is zero */
3738 if (!(min == 0 && IS_UNSIGNED (cetype)))
3740 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3741 ic = newiCodeCondition (boundary, falseLabel, NULL);
3745 /* now for upper bounds */
3746 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3747 ic = newiCodeCondition (boundary, falseLabel, NULL);
3751 /* if the min is not zero then we no make it zero */
3754 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3755 if (!IS_LITERAL(getSpec(operandType(cond))))
3756 setOperandType (cond, UCHARTYPE);
3759 /* now create the jumptable */
3760 ic = newiCode (JUMPTABLE, NULL, NULL);
3761 IC_JTCOND (ic) = cond;
3762 IC_JTLABELS (ic) = labels;
3767 /*-----------------------------------------------------------------*/
3768 /* geniCodeSwitch - changes a switch to a if statement */
3769 /*-----------------------------------------------------------------*/
3771 geniCodeSwitch (ast * tree,int lvl)
3774 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3775 value *caseVals = tree->values.switchVals.swVals;
3776 symbol *trueLabel, *falseLabel;
3778 /* If the condition is a literal, then just jump to the */
3779 /* appropriate case label. */
3780 if (IS_LITERAL(getSpec(operandType(cond))))
3782 int switchVal, caseVal;
3784 switchVal = (int) floatFromVal (cond->operand.valOperand);
3787 caseVal = (int) floatFromVal (caseVals);
3788 if (caseVal == switchVal)
3790 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3791 tree->values.switchVals.swNum, caseVal);
3792 trueLabel = newiTempLabel (buffer);
3793 geniCodeGoto (trueLabel);
3796 caseVals = caseVals->next;
3798 goto defaultOrBreak;
3801 /* If cond is volatile, it might change while we are trying to */
3802 /* find the matching case. To avoid this possibility, make a */
3803 /* non-volatile copy to use instead. */
3804 if (IS_OP_VOLATILE (cond))
3809 newcond = newiTempOperand (operandType (cond), TRUE);
3810 newcond->isvolatile = 0;
3811 ic = newiCode ('=', NULL, cond);
3812 IC_RESULT (ic) = newcond;
3817 /* if we can make this a jump table */
3818 if (geniCodeJumpTable (cond, caseVals, tree))
3819 goto jumpTable; /* no need for the comparison */
3821 /* for the cases defined do */
3825 operand *compare = geniCodeLogic (cond,
3826 operandFromValue (caseVals),
3829 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3830 tree->values.switchVals.swNum,
3831 (int) floatFromVal (caseVals));
3832 trueLabel = newiTempLabel (buffer);
3834 ic = newiCodeCondition (compare, trueLabel, NULL);
3836 caseVals = caseVals->next;
3841 /* if default is present then goto break else break */
3842 if (tree->values.switchVals.swDefault)
3844 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3848 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3851 falseLabel = newiTempLabel (buffer);
3852 geniCodeGoto (falseLabel);
3855 ast2iCode (tree->right,lvl+1);
3858 /*-----------------------------------------------------------------*/
3859 /* geniCodeInline - intermediate code for inline assembler */
3860 /*-----------------------------------------------------------------*/
3862 geniCodeInline (ast * tree)
3866 ic = newiCode (INLINEASM, NULL, NULL);
3867 IC_INLINE (ic) = tree->values.inlineasm;
3871 /*-----------------------------------------------------------------*/
3872 /* geniCodeArrayInit - intermediate code for array initializer */
3873 /*-----------------------------------------------------------------*/
3875 geniCodeArrayInit (ast * tree, operand *array)
3879 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3880 ic = newiCode (ARRAYINIT, array, NULL);
3881 IC_ARRAYILIST (ic) = tree->values.constlist;
3883 operand *left=newOperand(), *right=newOperand();
3884 left->type=right->type=SYMBOL;
3885 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3886 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3887 ic = newiCode (ARRAYINIT, left, right);
3892 /*-----------------------------------------------------------------*/
3893 /* geniCodeCritical - intermediate code for a critical statement */
3894 /*-----------------------------------------------------------------*/
3896 geniCodeCritical (ast *tree, int lvl)
3902 if (!options.stackAuto)
3904 type = newLink(SPECIFIER);
3905 SPEC_VOLATILE(type) = 1;
3906 SPEC_NOUN(type) = V_BIT;
3907 SPEC_SCLS(type) = S_BIT;
3908 SPEC_BLEN(type) = 1;
3909 SPEC_BSTR(type) = 0;
3910 op = newiTempOperand(type, 1);
3913 /* If op is NULL, the original interrupt state will saved on */
3914 /* the stack. Otherwise, it will be saved in op. */
3916 /* Generate a save of the current interrupt state & disable */
3917 ic = newiCode (CRITICAL, NULL, NULL);
3918 IC_RESULT (ic) = op;
3921 /* Generate the critical code sequence */
3922 if (tree->left && tree->left->type == EX_VALUE)
3923 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3925 ast2iCode (tree->left,lvl+1);
3927 /* Generate a restore of the original interrupt state */
3928 ic = newiCode (ENDCRITICAL, NULL, op);
3932 /*-----------------------------------------------------------------*/
3933 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3934 /* particular case. Ie : assigning or dereferencing array or ptr */
3935 /*-----------------------------------------------------------------*/
3936 set * lvaluereqSet = NULL;
3937 typedef struct lvalItem
3944 /*-----------------------------------------------------------------*/
3945 /* addLvaluereq - add a flag for lvalreq for current ast level */
3946 /*-----------------------------------------------------------------*/
3947 void addLvaluereq(int lvl)
3949 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3952 addSetHead(&lvaluereqSet,lpItem);
3955 /*-----------------------------------------------------------------*/
3956 /* delLvaluereq - del a flag for lvalreq for current ast level */
3957 /*-----------------------------------------------------------------*/
3961 lpItem = getSet(&lvaluereqSet);
3962 if(lpItem) Safe_free(lpItem);
3964 /*-----------------------------------------------------------------*/
3965 /* clearLvaluereq - clear lvalreq flag */
3966 /*-----------------------------------------------------------------*/
3967 void clearLvaluereq()
3970 lpItem = peekSet(lvaluereqSet);
3971 if(lpItem) lpItem->req = 0;
3973 /*-----------------------------------------------------------------*/
3974 /* getLvaluereq - get the last lvalreq level */
3975 /*-----------------------------------------------------------------*/
3976 int getLvaluereqLvl()
3979 lpItem = peekSet(lvaluereqSet);
3980 if(lpItem) return lpItem->lvl;
3983 /*-----------------------------------------------------------------*/
3984 /* isLvaluereq - is lvalreq valid for this level ? */
3985 /*-----------------------------------------------------------------*/
3986 int isLvaluereq(int lvl)
3989 lpItem = peekSet(lvaluereqSet);
3990 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3994 /*-----------------------------------------------------------------*/
3995 /* ast2iCode - creates an icodeList from an ast */
3996 /*-----------------------------------------------------------------*/
3998 ast2iCode (ast * tree,int lvl)
4000 operand *left = NULL;
4001 operand *right = NULL;
4005 /* set the global variables for filename & line number */
4007 filename = tree->filename;
4009 lineno = tree->lineno;
4011 block = tree->block;
4013 scopeLevel = tree->level;
4015 seqPoint = tree->seqPoint;
4017 if (tree->type == EX_VALUE)
4018 return operandFromValue (tree->opval.val);
4020 if (tree->type == EX_LINK)
4021 return operandFromLink (tree->opval.lnk);
4023 /* if we find a nullop */
4024 if (tree->type == EX_OP &&
4025 (tree->opval.op == NULLOP ||
4026 tree->opval.op == BLOCK))
4028 if (tree->left && tree->left->type == EX_VALUE)
4029 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4031 ast2iCode (tree->left,lvl+1);
4032 if (tree->right && tree->right->type == EX_VALUE)
4033 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4035 ast2iCode (tree->right,lvl+1);
4039 /* special cases for not evaluating */
4040 if (tree->opval.op != ':' &&
4041 tree->opval.op != '?' &&
4042 tree->opval.op != CALL &&
4043 tree->opval.op != IFX &&
4044 tree->opval.op != AND_OP &&
4045 tree->opval.op != OR_OP &&
4046 tree->opval.op != LABEL &&
4047 tree->opval.op != GOTO &&
4048 tree->opval.op != SWITCH &&
4049 tree->opval.op != FUNCTION &&
4050 tree->opval.op != INLINEASM &&
4051 tree->opval.op != CRITICAL)
4054 if (IS_ASSIGN_OP (tree->opval.op) ||
4055 IS_DEREF_OP (tree) ||
4056 (tree->opval.op == '&' && !tree->right) ||
4057 tree->opval.op == PTR_OP)
4060 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4061 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4064 left = operandFromAst (tree->left,lvl);
4066 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4067 left = geniCodeRValue (left, TRUE);
4071 left = operandFromAst (tree->left,lvl);
4073 if (tree->opval.op == INC_OP ||
4074 tree->opval.op == DEC_OP)
4077 right = operandFromAst (tree->right,lvl);
4082 right = operandFromAst (tree->right,lvl);
4086 /* now depending on the type of operand */
4087 /* this will be a biggy */
4088 switch (tree->opval.op)
4091 case '[': /* array operation */
4093 //sym_link *ltype = operandType (left);
4094 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4095 left = geniCodeRValue (left, FALSE);
4096 right = geniCodeRValue (right, TRUE);
4099 return geniCodeArray (left, right,lvl);
4101 case '.': /* structure dereference */
4102 if (IS_PTR (operandType (left)))
4103 left = geniCodeRValue (left, TRUE);
4105 left = geniCodeRValue (left, FALSE);
4107 return geniCodeStruct (left, right, tree->lvalue);
4109 case PTR_OP: /* structure pointer dereference */
4112 pType = operandType (left);
4113 left = geniCodeRValue (left, TRUE);
4115 setOClass (pType, getSpec (operandType (left)));
4118 return geniCodeStruct (left, right, tree->lvalue);
4120 case INC_OP: /* increment operator */
4122 return geniCodePostInc (left);
4124 return geniCodePreInc (right, tree->lvalue);
4126 case DEC_OP: /* decrement operator */
4128 return geniCodePostDec (left);
4130 return geniCodePreDec (right, tree->lvalue);
4132 case '&': /* bitwise and or address of operator */
4134 { /* this is a bitwise operator */
4135 left = geniCodeRValue (left, FALSE);
4136 right = geniCodeRValue (right, FALSE);
4137 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4140 return geniCodeAddressOf (left);
4142 case '|': /* bitwise or & xor */
4144 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4145 geniCodeRValue (right, FALSE),
4150 return geniCodeDivision (geniCodeRValue (left, FALSE),
4151 geniCodeRValue (right, FALSE),
4152 getResultTypeFromType (tree->ftype));
4155 return geniCodeModulus (geniCodeRValue (left, FALSE),
4156 geniCodeRValue (right, FALSE),
4157 getResultTypeFromType (tree->ftype));
4160 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4161 geniCodeRValue (right, FALSE),
4162 getResultTypeFromType (tree->ftype));
4164 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4168 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4169 geniCodeRValue (right, FALSE),
4170 getResultTypeFromType (tree->ftype));
4172 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4176 return geniCodeAdd (geniCodeRValue (left, FALSE),
4177 geniCodeRValue (right, FALSE),
4178 getResultTypeFromType (tree->ftype),
4181 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4184 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4185 geniCodeRValue (right, FALSE),
4186 getResultTypeFromType (tree->ftype));
4189 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4190 geniCodeRValue (right, FALSE));
4192 #if 0 // this indeed needs a second thought
4196 // let's keep this simple: get the rvalue we need
4197 op=geniCodeRValue (right, FALSE);
4198 // now cast it to whatever we want
4199 op=geniCodeCast (operandType(left), op, FALSE);
4200 // if this is going to be used as an lvalue, make it so
4206 #else // bug #604575, is it a bug ????
4207 return geniCodeCast (operandType (left),
4208 geniCodeRValue (right, FALSE), FALSE);
4215 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4220 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4221 setOperandType (op, UCHARTYPE);
4228 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4229 geniCodeRValue (right, FALSE),
4231 setOperandType (op, (tree->opval.op == GETWORD) ? UINTTYPE : UCHARTYPE);
4236 return geniCodeLogicAndOr (tree, lvl);
4243 /* different compilers (even different gccs) evaluate
4244 the two calls in a different order. to get the same
4245 result on all machines we've to specify a clear sequence.
4246 return geniCodeLogic (geniCodeRValue (left, FALSE),
4247 geniCodeRValue (right, FALSE),
4251 operand *leftOp, *rightOp;
4253 leftOp = geniCodeRValue (left , FALSE);
4254 rightOp = geniCodeRValue (right, FALSE);
4256 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4259 return geniCodeConditional (tree,lvl);
4262 return operandFromLit (getSize (tree->right->ftype));
4266 sym_link *rtype = operandType (right);
4267 sym_link *ltype = operandType (left);
4268 if (IS_PTR (rtype) && IS_ITEMP (right)
4269 && right->isaddr && compareType (rtype->next, ltype) == 1)
4270 right = geniCodeRValue (right, TRUE);
4272 right = geniCodeRValue (right, FALSE);
4274 geniCodeAssign (left, right, 0, 1);
4279 geniCodeAssign (left,
4280 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4282 geniCodeRValue (right, FALSE),
4283 getResultTypeFromType (tree->ftype)),
4288 geniCodeAssign (left,
4289 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4291 geniCodeRValue (right, FALSE),
4292 getResultTypeFromType (tree->ftype)),
4296 geniCodeAssign (left,
4297 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4299 geniCodeRValue (right, FALSE),
4300 getResultTypeFromType (tree->ftype)),
4304 sym_link *rtype = operandType (right);
4305 sym_link *ltype = operandType (left);
4306 if (IS_PTR (rtype) && IS_ITEMP (right)
4307 && right->isaddr && compareType (rtype->next, ltype) == 1)
4308 right = geniCodeRValue (right, TRUE);
4310 right = geniCodeRValue (right, FALSE);
4313 return geniCodeAssign (left,
4314 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4317 getResultTypeFromType (tree->ftype),
4323 sym_link *rtype = operandType (right);
4324 sym_link *ltype = operandType (left);
4325 if (IS_PTR (rtype) && IS_ITEMP (right)
4326 && right->isaddr && compareType (rtype->next, ltype) == 1)
4328 right = geniCodeRValue (right, TRUE);
4332 right = geniCodeRValue (right, FALSE);
4335 geniCodeAssign (left,
4336 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4339 getResultTypeFromType (tree->ftype)),
4344 geniCodeAssign (left,
4345 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4347 geniCodeRValue (right, FALSE),
4348 getResultTypeFromType (tree->ftype)),
4352 geniCodeAssign (left,
4353 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4355 geniCodeRValue (right, FALSE)), 0, 1);
4358 geniCodeAssign (left,
4359 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4361 geniCodeRValue (right, FALSE),
4363 operandType (left)), 0, 1);
4366 geniCodeAssign (left,
4367 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4369 geniCodeRValue (right, FALSE),
4371 operandType (left)), 0, 1);
4374 geniCodeAssign (left,
4375 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4377 geniCodeRValue (right, FALSE),
4379 operandType (left)), 0, 1);
4381 return geniCodeRValue (right, FALSE);
4384 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4387 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4388 return ast2iCode (tree->right,lvl+1);
4391 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4392 return ast2iCode (tree->right,lvl+1);
4395 geniCodeFunctionBody (tree,lvl);
4399 geniCodeReturn (right);
4403 geniCodeIfx (tree,lvl);
4407 geniCodeSwitch (tree,lvl);
4411 geniCodeInline (tree);
4415 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4419 geniCodeCritical (tree, lvl);
4425 /*-----------------------------------------------------------------*/
4426 /* reverseICChain - gets from the list and creates a linkedlist */
4427 /*-----------------------------------------------------------------*/
4434 while ((loop = getSet (&iCodeChain)))
4446 /*-----------------------------------------------------------------*/
4447 /* iCodeFromAst - given an ast will convert it to iCode */
4448 /*-----------------------------------------------------------------*/
4450 iCodeFromAst (ast * tree)
4452 returnLabel = newiTempLabel ("_return");
4453 entryLabel = newiTempLabel ("_entry");
4455 return reverseiCChain ();
4458 static const char *opTypeToStr(OPTYPE op)
4462 case SYMBOL: return "symbol";
4463 case VALUE: return "value";
4464 case TYPE: return "type";
4466 return "undefined type";
4470 operand *validateOpType(operand *op,
4477 if (op && op->type == type)
4482 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4483 " expected %s, got %s\n",
4484 macro, args, file, line,
4485 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4487 return op; // never reached, makes compiler happy.