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 ic = newiCode ('*', left, right); /* normal multiplication */
2134 /* if the size left or right > 1 then support routine */
2135 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2139 IC_RESULT (ic) = newiTempOperand (resType, 1);
2142 return IC_RESULT (ic);
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodeDivision - gen intermediate code for division */
2147 /*-----------------------------------------------------------------*/
2149 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2154 sym_link *rtype = operandType (right);
2155 sym_link *retype = getSpec (rtype);
2156 sym_link *ltype = operandType (left);
2157 sym_link *letype = getSpec (ltype);
2159 resType = usualBinaryConversions (&left, &right, resultType, '/');
2161 /* if the right is a literal & power of 2
2162 and left is unsigned then make it a
2164 if (IS_LITERAL (retype) &&
2165 !IS_FLOAT (letype) &&
2166 !IS_FIXED (letype) &&
2167 IS_UNSIGNED(letype) &&
2168 ((p2 = powof2 ((TYPE_TARGET_ULONG)
2169 floatFromVal (right->operand.valOperand))) > 0)) {
2170 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2174 ic = newiCode ('/', left, right); /* normal division */
2175 /* if the size left or right > 1 then support routine */
2176 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2179 IC_RESULT (ic) = newiTempOperand (resType, 0);
2182 return IC_RESULT (ic);
2184 /*-----------------------------------------------------------------*/
2185 /* geniCodeModulus - gen intermediate code for modulus */
2186 /*-----------------------------------------------------------------*/
2188 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2194 /* if they are both literal then we know the result */
2195 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2196 return operandFromValue (valMod (left->operand.valOperand,
2197 right->operand.valOperand));
2199 resType = usualBinaryConversions (&left, &right, resultType, '%');
2201 /* now they are the same size */
2202 ic = newiCode ('%', left, right);
2204 /* if the size left or right > 1 then support routine */
2205 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2207 IC_RESULT (ic) = newiTempOperand (resType, 0);
2210 return IC_RESULT (ic);
2213 /*-----------------------------------------------------------------*/
2214 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2215 /*-----------------------------------------------------------------*/
2217 geniCodePtrPtrSubtract (operand * left, operand * right)
2223 /* if they are both literals then */
2224 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2226 result = operandFromValue (valMinus (left->operand.valOperand,
2227 right->operand.valOperand));
2231 ic = newiCode ('-', left, right);
2233 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2237 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2241 // should we really do this? is this ANSI?
2242 return geniCodeDivision (result,
2243 operandFromLit (getSize (ltype->next)),
2247 /*-----------------------------------------------------------------*/
2248 /* geniCodeSubtract - generates code for subtraction */
2249 /*-----------------------------------------------------------------*/
2251 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2258 /* if they both pointers then */
2259 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2260 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2261 return geniCodePtrPtrSubtract (left, right);
2263 /* if they are both literal then we know the result */
2264 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2265 && left->isLiteral && right->isLiteral)
2266 return operandFromValue (valMinus (left->operand.valOperand,
2267 right->operand.valOperand));
2269 /* if left is an array or pointer */
2270 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2272 isarray = left->isaddr;
2273 right = geniCodeMultiply (right,
2274 operandFromLit (getSize (ltype->next)),
2275 (getArraySizePtr(left) >= INTSIZE) ?
2278 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2281 { /* make them the same size */
2282 resType = usualBinaryConversions (&left, &right, resultType, '-');
2285 ic = newiCode ('-', left, right);
2287 IC_RESULT (ic) = newiTempOperand (resType, 1);
2288 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2290 /* if left or right is a float */
2291 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2292 || IS_FIXED (ltype) || IS_FIXED (rtype))
2296 return IC_RESULT (ic);
2299 /*-----------------------------------------------------------------*/
2300 /* geniCodeAdd - generates iCode for addition */
2301 /*-----------------------------------------------------------------*/
2303 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2312 /* if the right side is LITERAL zero */
2313 /* return the left side */
2314 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2317 /* if left is literal zero return right */
2318 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2321 /* if left is a pointer then size */
2322 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2324 isarray = left->isaddr;
2325 // there is no need to multiply with 1
2326 if (getSize (ltype->next) != 1)
2328 size = operandFromLit (getSize (ltype->next));
2329 SPEC_USIGN (getSpec (operandType (size))) = 1;
2330 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2331 right = geniCodeMultiply (right, size, resultType);
2332 /* Even if right is a 'unsigned char',
2333 the result will be a 'signed int' due to the promotion rules.
2334 It doesn't make sense when accessing arrays, so let's fix it here: */
2336 SPEC_USIGN (getSpec (operandType (right))) = 1;
2338 resType = copyLinkChain (ltype);
2341 { // make them the same size
2342 resType = usualBinaryConversions (&left, &right, resultType, '+');
2345 /* if they are both literals then we know */
2346 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2347 && left->isLiteral && right->isLiteral)
2348 return operandFromValue (valPlus (valFromType (ltype),
2349 valFromType (rtype)));
2351 ic = newiCode ('+', left, right);
2353 IC_RESULT (ic) = newiTempOperand (resType, 1);
2354 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2356 /* if left or right is a float then support
2358 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2359 || IS_FIXED (ltype) || IS_FIXED (rtype))
2364 return IC_RESULT (ic);
2368 /*-----------------------------------------------------------------*/
2369 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2370 /*-----------------------------------------------------------------*/
2372 aggrToPtr (sym_link * type, bool force)
2377 if (IS_PTR (type) && !force)
2380 etype = getSpec (type);
2381 ptype = newLink (DECLARATOR);
2385 /* set the pointer depending on the storage class */
2386 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2390 /*------------------------------------------------------------------*/
2391 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2392 /*------------------------------------------------------------------*/
2394 aggrToPtrDclType (sym_link * type, bool force)
2396 if (IS_PTR (type) && !force)
2397 return DCL_TYPE (type);
2399 /* return the pointer depending on the storage class */
2400 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2403 /*-----------------------------------------------------------------*/
2404 /* geniCodeArray2Ptr - array to pointer */
2405 /*-----------------------------------------------------------------*/
2407 geniCodeArray2Ptr (operand * op)
2409 sym_link *optype = operandType (op);
2410 sym_link *opetype = getSpec (optype);
2412 /* set the pointer depending on the storage class */
2413 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2420 /*-----------------------------------------------------------------*/
2421 /* geniCodeArray - array access */
2422 /*-----------------------------------------------------------------*/
2424 geniCodeArray (operand * left, operand * right, int lvl)
2428 sym_link *ltype = operandType (left);
2430 RESULT_TYPE resultType;
2432 resultType = (getArraySizePtr(left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
2433 if (DCL_ELEM (ltype))
2435 if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
2436 resultType = RESULT_TYPE_CHAR;
2441 if (IS_PTR (ltype->next) && left->isaddr)
2443 left = geniCodeRValue (left, FALSE);
2446 return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl),
2449 size = operandFromLit (getSize (ltype->next));
2450 SPEC_USIGN (getSpec (operandType (size))) = 1;
2451 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2452 right = geniCodeMultiply (right, size, resultType);
2453 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2454 It doesn't make sense when accessing arrays, so let's fix it here: */
2456 SPEC_USIGN (getSpec (operandType (right))) = 1;
2457 /* we can check for limits here */
2458 /* already done in SDCCast.c
2459 if (isOperandLiteral (right) &&
2462 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2464 werror (W_IDX_OUT_OF_BOUNDS,
2465 (int) operandLitValue (right) / getSize (ltype->next),
2470 ic = newiCode ('+', left, right);
2472 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2473 !IS_AGGREGATE (ltype->next) &&
2474 !IS_PTR (ltype->next))
2475 ? ltype : ltype->next), 0);
2477 if (!IS_AGGREGATE (ltype->next))
2479 IC_RESULT (ic)->isaddr = 1;
2480 IC_RESULT (ic)->aggr2ptr = 1;
2484 return IC_RESULT (ic);
2487 /*-----------------------------------------------------------------*/
2488 /* geniCodeStruct - generates intermediate code for structures */
2489 /*-----------------------------------------------------------------*/
2491 geniCodeStruct (operand * left, operand * right, bool islval)
2494 sym_link *type = operandType (left);
2495 sym_link *etype = getSpec (type);
2497 symbol *element = getStructElement (SPEC_STRUCT (etype),
2498 right->operand.symOperand);
2500 wassert(IS_SYMOP(right));
2502 /* add the offset */
2503 ic = newiCode ('+', left, operandFromLit (element->offset));
2505 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2507 /* preserve the storage & output class of the struct */
2508 /* as well as the volatile attribute */
2509 retype = getSpec (operandType (IC_RESULT (ic)));
2510 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2511 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2512 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2513 SPEC_CONST (retype) |= SPEC_CONST (etype);
2515 if (IS_PTR (element->type))
2516 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2518 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2521 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2524 /*-----------------------------------------------------------------*/
2525 /* geniCodePostInc - generate int code for Post increment */
2526 /*-----------------------------------------------------------------*/
2528 geniCodePostInc (operand * op)
2532 sym_link *optype = operandType (op);
2534 operand *rv = (IS_ITEMP (op) ?
2535 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2537 sym_link *rvtype = operandType (rv);
2540 /* if this is not an address we have trouble */
2543 werror (E_LVALUE_REQUIRED, "++");
2547 rOp = newiTempOperand (rvtype, 0);
2548 OP_SYMBOL(rOp)->noSpilLoc = 1;
2551 OP_SYMBOL(rv)->noSpilLoc = 1;
2553 geniCodeAssign (rOp, rv, 0, 0);
2555 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2557 werror(W_SIZEOF_VOID);
2558 if (IS_FLOAT (rvtype))
2559 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2560 else if (IS_FIXED16X16 (rvtype))
2561 ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2563 ic = newiCode ('+', rv, operandFromLit (size));
2565 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2568 geniCodeAssign (op, result, 0, 0);
2574 /*-----------------------------------------------------------------*/
2575 /* geniCodePreInc - generate code for preIncrement */
2576 /*-----------------------------------------------------------------*/
2578 geniCodePreInc (operand * op, bool lvalue)
2581 sym_link *optype = operandType (op);
2582 operand *rop = (IS_ITEMP (op) ?
2583 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2585 sym_link *roptype = operandType (rop);
2591 werror (E_LVALUE_REQUIRED, "++");
2595 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2597 werror(W_SIZEOF_VOID);
2598 if (IS_FLOAT (roptype))
2599 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2600 else if (IS_FIXED16X16 (roptype))
2601 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2603 ic = newiCode ('+', rop, operandFromLit (size));
2604 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2607 (void) geniCodeAssign (op, result, 0, 0);
2608 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2614 /*-----------------------------------------------------------------*/
2615 /* geniCodePostDec - generates code for Post decrement */
2616 /*-----------------------------------------------------------------*/
2618 geniCodePostDec (operand * op)
2622 sym_link *optype = operandType (op);
2624 operand *rv = (IS_ITEMP (op) ?
2625 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2627 sym_link *rvtype = operandType (rv);
2630 /* if this is not an address we have trouble */
2633 werror (E_LVALUE_REQUIRED, "--");
2637 rOp = newiTempOperand (rvtype, 0);
2638 OP_SYMBOL(rOp)->noSpilLoc = 1;
2641 OP_SYMBOL(rv)->noSpilLoc = 1;
2643 geniCodeAssign (rOp, rv, 0, 0);
2645 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2647 werror(W_SIZEOF_VOID);
2648 if (IS_FLOAT (rvtype))
2649 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2650 else if (IS_FIXED16X16 (rvtype))
2651 ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2653 ic = newiCode ('-', rv, operandFromLit (size));
2655 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2658 geniCodeAssign (op, result, 0, 0);
2664 /*-----------------------------------------------------------------*/
2665 /* geniCodePreDec - generate code for pre decrement */
2666 /*-----------------------------------------------------------------*/
2668 geniCodePreDec (operand * op, bool lvalue)
2671 sym_link *optype = operandType (op);
2672 operand *rop = (IS_ITEMP (op) ?
2673 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2675 sym_link *roptype = operandType (rop);
2681 werror (E_LVALUE_REQUIRED, "--");
2685 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2687 werror(W_SIZEOF_VOID);
2688 if (IS_FLOAT (roptype))
2689 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2690 else if (IS_FIXED16X16 (roptype))
2691 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2693 ic = newiCode ('-', rop, operandFromLit (size));
2694 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2697 (void) geniCodeAssign (op, result, 0, 0);
2698 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2705 /*-----------------------------------------------------------------*/
2706 /* geniCodeBitwise - gen int code for bitWise operators */
2707 /*-----------------------------------------------------------------*/
2709 geniCodeBitwise (operand * left, operand * right,
2710 int oper, sym_link * resType)
2714 left = geniCodeCast (resType, left, TRUE);
2715 right = geniCodeCast (resType, right, TRUE);
2717 ic = newiCode (oper, left, right);
2718 IC_RESULT (ic) = newiTempOperand (resType, 0);
2721 return IC_RESULT (ic);
2724 /*-----------------------------------------------------------------*/
2725 /* geniCodeAddressOf - gens icode for '&' address of operator */
2726 /*-----------------------------------------------------------------*/
2728 geniCodeAddressOf (operand * op)
2732 sym_link *optype = operandType (op);
2733 sym_link *opetype = getSpec (optype);
2735 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2737 op = operandFromOperand (op);
2742 /* lvalue check already done in decorateType */
2743 /* this must be a lvalue */
2744 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2745 /* werror (E_LVALUE_REQUIRED,"&"); */
2749 p = newLink (DECLARATOR);
2751 /* set the pointer depending on the storage class */
2752 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2754 p->next = copyLinkChain (optype);
2756 /* if already a temp */
2759 setOperandType (op, p);
2764 /* otherwise make this of the type coming in */
2765 ic = newiCode (ADDRESS_OF, op, NULL);
2766 IC_RESULT (ic) = newiTempOperand (p, 1);
2767 IC_RESULT (ic)->isaddr = 0;
2769 return IC_RESULT (ic);
2772 /*-----------------------------------------------------------------*/
2773 /* setOClass - sets the output class depending on the pointer type */
2774 /*-----------------------------------------------------------------*/
2776 setOClass (sym_link * ptr, sym_link * spec)
2778 switch (DCL_TYPE (ptr))
2781 SPEC_OCLS (spec) = data;
2785 SPEC_OCLS (spec) = generic;
2789 SPEC_OCLS (spec) = xdata;
2793 SPEC_OCLS (spec) = code;
2797 SPEC_OCLS (spec) = idata;
2801 SPEC_OCLS (spec) = xstack;
2805 SPEC_OCLS (spec) = eeprom;
2814 /*-----------------------------------------------------------------*/
2815 /* geniCodeDerefPtr - dereference pointer with '*' */
2816 /*-----------------------------------------------------------------*/
2818 geniCodeDerefPtr (operand * op,int lvl)
2820 sym_link *rtype, *retype;
2821 sym_link *optype = operandType (op);
2823 // if this is an array then array access
2824 if (IS_ARRAY (optype)) {
2825 // don't worry, this will be optimized out later
2826 return geniCodeArray (op, operandFromLit (0), lvl);
2829 // just in case someone screws up
2830 wassert (IS_PTR (optype));
2832 if (IS_TRUE_SYMOP (op))
2835 op = geniCodeRValue (op, TRUE);
2838 /* now get rid of the pointer part */
2839 if (isLvaluereq(lvl) && IS_ITEMP (op))
2841 retype = getSpec (rtype = copyLinkChain (optype));
2845 retype = getSpec (rtype = copyLinkChain (optype->next));
2846 /* outputclass needs 2b updated */
2847 setOClass (optype, retype);
2850 op->isGptr = IS_GENPTR (optype);
2852 op->isaddr = (IS_PTR (rtype) ||
2853 IS_STRUCT (rtype) ||
2859 if (!isLvaluereq(lvl))
2860 op = geniCodeRValue (op, TRUE);
2862 setOperandType (op, rtype);
2867 /*-----------------------------------------------------------------*/
2868 /* geniCodeUnaryMinus - does a unary minus of the operand */
2869 /*-----------------------------------------------------------------*/
2871 geniCodeUnaryMinus (operand * op)
2874 sym_link *optype = operandType (op);
2876 if (IS_LITERAL (optype))
2877 return operandFromLit (-floatFromVal (op->operand.valOperand));
2879 ic = newiCode (UNARYMINUS, op, NULL);
2880 IC_RESULT (ic) = newiTempOperand (optype, 0);
2882 return IC_RESULT (ic);
2885 /*-----------------------------------------------------------------*/
2886 /* geniCodeLeftShift - gen i code for left shift */
2887 /*-----------------------------------------------------------------*/
2889 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2894 ic = newiCode (LEFT_OP, left, right);
2896 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2897 IC_RESULT (ic) = newiTempOperand (resType, 0);
2899 return IC_RESULT (ic);
2902 /*-----------------------------------------------------------------*/
2903 /* geniCodeRightShift - gen i code for right shift */
2904 /*-----------------------------------------------------------------*/
2906 geniCodeRightShift (operand * left, operand * right)
2910 ic = newiCode (RIGHT_OP, left, right);
2911 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2913 return IC_RESULT (ic);
2916 /*-----------------------------------------------------------------*/
2917 /* geniCodeLogic- logic code */
2918 /*-----------------------------------------------------------------*/
2920 geniCodeLogic (operand * left, operand * right, int op)
2924 sym_link *rtype = operandType (right);
2925 sym_link *ltype = operandType (left);
2927 /* left is integral type and right is literal then
2928 check if the literal value is within bounds */
2929 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2931 CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
2934 case CCR_ALWAYS_TRUE:
2935 case CCR_ALWAYS_FALSE:
2936 if (!options.lessPedantic)
2937 werror (W_COMP_RANGE, "true resp. false");
2938 return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
2944 /* if one operand is a pointer and the other is a literal generic void pointer,
2945 change the type of the literal generic void pointer to match the other pointer */
2946 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2947 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2949 /* find left's definition */
2950 ic = (iCode *) setFirstItem (iCodeChain);
2953 if (((ic->op == CAST) || (ic->op == '='))
2954 && isOperandEqual(left, IC_RESULT (ic)))
2957 ic = setNextItem (iCodeChain);
2959 /* if casting literal to generic pointer, then cast to rtype instead */
2960 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2962 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2963 ltype = operandType(left);
2966 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2967 && IS_PTR (ltype) && !IS_GENPTR(ltype))
2969 /* find right's definition */
2970 ic = (iCode *) setFirstItem (iCodeChain);
2973 if (((ic->op == CAST) || (ic->op == '='))
2974 && isOperandEqual(right, IC_RESULT (ic)))
2977 ic = setNextItem (iCodeChain);
2979 /* if casting literal to generic pointer, then cast to rtype instead */
2980 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2982 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2983 rtype = operandType(right);
2987 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_BIT, 0);
2989 ic = newiCode (op, left, right);
2990 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2992 /* if comparing float
2993 and not a '==' || '!=' || '&&' || '||' (these
2995 if (IS_FLOAT(ctype) &&
3002 /* if comparing a fixed type use support functions */
3003 if (IS_FIXED(ctype))
3007 return IC_RESULT (ic);
3010 /*-----------------------------------------------------------------*/
3011 /* geniCodeLogicAndOr - && || operations */
3012 /*-----------------------------------------------------------------*/
3014 geniCodeLogicAndOr (ast *tree, int lvl)
3018 symbol *falseLabel = newiTempLabel (NULL);
3019 symbol *trueLabel = newiTempLabel (NULL);
3020 symbol *exitLabel = newiTempLabel (NULL);
3021 operand *op, *result, *condition;
3023 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3024 They can be reenabled by executing the following block. If you find
3025 a decent optimization you could start right here:
3030 operand *leftOp, *rightOp;
3032 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3033 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3035 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3039 /* generate two IFX for the '&&' or '||' op */
3041 /* evaluate left operand */
3042 condition = ast2iCode (tree->left, lvl + 1);
3043 op = geniCodeRValue (condition, FALSE);
3045 /* test left operand */
3046 if (tree->opval.op == AND_OP)
3047 ic = newiCodeCondition (op, NULL, falseLabel);
3049 ic = newiCodeCondition (op, trueLabel, NULL);
3052 /* evaluate right operand */
3053 condition = ast2iCode (tree->right, lvl + 1);
3054 op = geniCodeRValue (condition, FALSE);
3056 /* test right operand */
3057 ic = newiCodeCondition (op, trueLabel, NULL);
3060 /* store 0 or 1 in result */
3061 type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
3062 result = newiTempOperand (type, 1);
3064 geniCodeLabel (falseLabel);
3065 geniCodeAssign (result, operandFromLit (0), 0, 0);
3066 /* generate an unconditional goto */
3067 geniCodeGoto (exitLabel);
3069 geniCodeLabel (trueLabel);
3070 geniCodeAssign (result, operandFromLit (1), 0, 0);
3072 geniCodeLabel (exitLabel);
3077 /*-----------------------------------------------------------------*/
3078 /* geniCodeUnary - for a generic unary operation */
3079 /*-----------------------------------------------------------------*/
3081 geniCodeUnary (operand * op, int oper)
3083 iCode *ic = newiCode (oper, op, NULL);
3085 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3087 return IC_RESULT (ic);
3090 /*-----------------------------------------------------------------*/
3091 /* geniCodeBinary - for a generic binary operation */
3092 /*-----------------------------------------------------------------*/
3094 geniCodeBinary (operand * left, operand * right, int oper)
3096 iCode *ic = newiCode (oper, left, right);
3098 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3100 return IC_RESULT (ic);
3103 /*-----------------------------------------------------------------*/
3104 /* geniCodeConditional - geniCode for '?' ':' operation */
3105 /*-----------------------------------------------------------------*/
3107 geniCodeConditional (ast * tree,int lvl)
3110 symbol *falseLabel = newiTempLabel (NULL);
3111 symbol *exitLabel = newiTempLabel (NULL);
3112 operand *cond = ast2iCode (tree->left,lvl+1);
3113 operand *true, *false, *result;
3115 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3119 true = ast2iCode (tree->right->left,lvl+1);
3121 /* move the value to a new Operand */
3122 result = newiTempOperand (tree->right->ftype, 0);
3123 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3125 /* generate an unconditional goto */
3126 geniCodeGoto (exitLabel);
3128 /* now for the right side */
3129 geniCodeLabel (falseLabel);
3131 false = ast2iCode (tree->right->right,lvl+1);
3132 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3134 /* create the exit label */
3135 geniCodeLabel (exitLabel);
3140 /*-----------------------------------------------------------------*/
3141 /* geniCodeAssign - generate code for assignment */
3142 /*-----------------------------------------------------------------*/
3144 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3147 sym_link *ltype = operandType (left);
3148 sym_link *rtype = operandType (right);
3150 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3152 werror (E_LVALUE_REQUIRED, "assignment");
3156 /* left is integral type and right is literal then
3157 check if the literal value is within bounds */
3158 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
3159 checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL &&
3160 !options.lessPedantic)
3162 werror (W_LIT_OVERFLOW);
3165 /* if the left & right type don't exactly match */
3166 /* if pointer set then make sure the check is
3167 done with the type & not the pointer */
3168 /* then cast rights type to left */
3170 /* first check the type for pointer assignement */
3171 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3172 compareType (ltype, rtype) <= 0)
3174 if (compareType (ltype->next, rtype) < 0)
3175 right = geniCodeCast (ltype->next, right, TRUE);
3177 else if (compareType (ltype, rtype) < 0)
3178 right = geniCodeCast (ltype, right, TRUE);
3180 /* If left is a true symbol & ! volatile
3181 create an assignment to temporary for
3182 the right & then assign this temporary
3183 to the symbol. This is SSA (static single
3184 assignment). Isn't it simple and folks have
3185 published mountains of paper on it */
3186 if (IS_TRUE_SYMOP (left) &&
3187 !isOperandVolatile (left, FALSE) &&
3188 isOperandGlobal (left))
3193 if (IS_TRUE_SYMOP (right))
3194 sym = OP_SYMBOL (right);
3195 ic = newiCode ('=', NULL, right);
3196 IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
3197 /* avoid double fetch from volatile right, see bug 1369874 */
3198 if (!isOperandVolatile (right, FALSE))
3199 SPIL_LOC (newRight) = sym;
3204 ic = newiCode ('=', NULL, right);
3205 IC_RESULT (ic) = left;
3208 /* if left isgptr flag is set then support
3209 routine will be required */
3213 ic->nosupdate = nosupdate;
3217 /*-----------------------------------------------------------------*/
3218 /* geniCodeDummyRead - generate code for dummy read */
3219 /*-----------------------------------------------------------------*/
3221 geniCodeDummyRead (operand * op)
3224 sym_link *type = operandType (op);
3226 if (!IS_VOLATILE(type))
3229 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3235 /*-----------------------------------------------------------------*/
3236 /* geniCodeSEParms - generate code for side effecting fcalls */
3237 /*-----------------------------------------------------------------*/
3239 geniCodeSEParms (ast * parms,int lvl)
3244 if (parms->type == EX_OP && parms->opval.op == PARAM)
3246 geniCodeSEParms (parms->left,lvl);
3247 geniCodeSEParms (parms->right,lvl);
3251 /* hack don't like this but too lazy to think of
3253 if (IS_ADDRESS_OF_OP (parms))
3254 parms->left->lvalue = 1;
3256 if (IS_CAST_OP (parms) &&
3257 IS_PTR (parms->ftype) &&
3258 IS_ADDRESS_OF_OP (parms->right))
3259 parms->right->left->lvalue = 1;
3261 parms->opval.oprnd =
3262 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3264 parms->type = EX_OPERAND;
3265 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3266 SPEC_ARGREG(parms->ftype);
3269 /*-----------------------------------------------------------------*/
3270 /* geniCodeParms - generates parameters */
3271 /*-----------------------------------------------------------------*/
3273 geniCodeParms (ast * parms, value *argVals, int *stack,
3274 sym_link * ftype, int lvl)
3282 if (argVals==NULL) {
3284 argVals = FUNC_ARGS (ftype);
3287 /* if this is a param node then do the left & right */
3288 if (parms->type == EX_OP && parms->opval.op == PARAM)
3290 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3291 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3295 /* get the parameter value */
3296 if (parms->type == EX_OPERAND)
3297 pval = parms->opval.oprnd;
3300 /* maybe this else should go away ?? */
3301 /* hack don't like this but too lazy to think of
3303 if (IS_ADDRESS_OF_OP (parms))
3304 parms->left->lvalue = 1;
3306 if (IS_CAST_OP (parms) &&
3307 IS_PTR (parms->ftype) &&
3308 IS_ADDRESS_OF_OP (parms->right))
3309 parms->right->left->lvalue = 1;
3311 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3314 /* if register parm then make it a send */
3315 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3316 IFFUNC_ISBUILTIN(ftype))
3318 ic = newiCode (SEND, pval, NULL);
3319 ic->argreg = SPEC_ARGREG(parms->etype);
3320 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3325 /* now decide whether to push or assign */
3326 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3330 operand *top = operandFromSymbol (argVals->sym);
3331 /* clear useDef and other bitVectors */
3332 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3333 geniCodeAssign (top, pval, 1, 0);
3337 sym_link *p = operandType (pval);
3339 ic = newiCode (IPUSH, pval, NULL);
3341 /* update the stack adjustment */
3342 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3347 argVals=argVals->next;
3351 /*-----------------------------------------------------------------*/
3352 /* geniCodeCall - generates temp code for calling */
3353 /*-----------------------------------------------------------------*/
3355 geniCodeCall (operand * left, ast * parms,int lvl)
3359 sym_link *type, *etype;
3363 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3364 !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3365 werror (E_FUNCTION_EXPECTED);
3366 return operandFromValue(valueFromLit(0));
3369 /* take care of parameters with side-effecting
3370 function calls in them, this is required to take care
3371 of overlaying function parameters */
3372 geniCodeSEParms (parms,lvl);
3374 ftype = operandType (left);
3375 if (IS_FUNCPTR (ftype))
3376 ftype = ftype->next;
3378 /* first the parameters */
3379 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3381 /* now call : if symbol then pcall */
3382 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3383 ic = newiCode (PCALL, left, NULL);
3385 ic = newiCode (CALL, left, NULL);
3388 type = copyLinkChain (ftype->next);
3389 etype = getSpec (type);
3390 SPEC_EXTR (etype) = 0;
3391 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3395 /* stack adjustment after call */
3396 ic->parmBytes = stack;
3401 /*-----------------------------------------------------------------*/
3402 /* geniCodeReceive - generate intermediate code for "receive" */
3403 /*-----------------------------------------------------------------*/
3405 geniCodeReceive (value * args, operand * func)
3407 unsigned char paramByteCounter = 0;
3409 /* for all arguments that are passed in registers */
3412 if (IS_REGPARM (args->etype))
3414 operand *opr = operandFromValue (args);
3416 symbol *sym = OP_SYMBOL (opr);
3419 /* we will use it after all optimizations
3420 and before liveRange calculation */
3421 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3424 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3425 options.stackAuto == 0 &&
3426 (!(options.model == MODEL_FLAT24)) )
3431 opl = newiTempOperand (args->type, 0);
3433 sym->reqv->key = sym->key;
3434 OP_SYMBOL (sym->reqv)->key = sym->key;
3435 OP_SYMBOL (sym->reqv)->isreqv = 1;
3436 OP_SYMBOL (sym->reqv)->islocal = 0;
3437 SPIL_LOC (sym->reqv) = sym;
3441 ic = newiCode (RECEIVE, func, NULL);
3442 ic->argreg = SPEC_ARGREG(args->etype);
3443 if (ic->argreg == 1) {
3444 currFunc->recvSize = getSize (sym->type);
3446 IC_RESULT (ic) = opr;
3448 /* misuse of parmBytes (normally used for functions)
3449 * to save estimated stack position of this argument.
3450 * Normally this should be zero for RECEIVE iCodes.
3451 * No idea if this causes side effects on other ports. - dw
3453 ic->parmBytes = paramByteCounter;
3455 /* what stack position do we have? */
3456 paramByteCounter += getSize (sym->type);
3465 /*-----------------------------------------------------------------*/
3466 /* geniCodeFunctionBody - create the function body */
3467 /*-----------------------------------------------------------------*/
3469 geniCodeFunctionBody (ast * tree,int lvl)
3476 /* reset the auto generation */
3482 func = ast2iCode (tree->left,lvl+1);
3483 fetype = getSpec (operandType (func));
3485 savelineno = lineno;
3486 lineno = OP_SYMBOL (func)->lineDef;
3487 /* create an entry label */
3488 geniCodeLabel (entryLabel);
3489 lineno = savelineno;
3491 /* create a proc icode */
3492 ic = newiCode (FUNCTION, func, NULL);
3493 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3498 /* for all parameters that are passed
3499 on registers add a "receive" */
3500 geniCodeReceive (tree->values.args, func);
3502 /* generate code for the body */
3503 ast2iCode (tree->right,lvl+1);
3505 /* create a label for return */
3506 geniCodeLabel (returnLabel);
3508 /* now generate the end proc */
3509 ic = newiCode (ENDFUNCTION, func, NULL);
3515 /*-----------------------------------------------------------------*/
3516 /* geniCodeReturn - gen icode for 'return' statement */
3517 /*-----------------------------------------------------------------*/
3519 geniCodeReturn (operand * op)
3523 /* if the operand is present force an rvalue */
3525 op = geniCodeRValue (op, FALSE);
3527 ic = newiCode (RETURN, op, NULL);
3531 /*-----------------------------------------------------------------*/
3532 /* geniCodeIfx - generates code for extended if statement */
3533 /*-----------------------------------------------------------------*/
3535 geniCodeIfx (ast * tree,int lvl)
3538 operand *condition = ast2iCode (tree->left,lvl+1);
3541 /* if condition is null then exit */
3545 condition = geniCodeRValue (condition, FALSE);
3547 cetype = getSpec (operandType (condition));
3548 /* if the condition is a literal */
3549 if (IS_LITERAL (cetype))
3551 if (floatFromVal (condition->operand.valOperand))
3553 if (tree->trueLabel)
3554 geniCodeGoto (tree->trueLabel);
3560 if (tree->falseLabel)
3561 geniCodeGoto (tree->falseLabel);
3566 if (tree->trueLabel)
3568 ic = newiCodeCondition (condition,
3573 if (tree->falseLabel)
3574 geniCodeGoto (tree->falseLabel);
3578 ic = newiCodeCondition (condition,
3585 ast2iCode (tree->right,lvl+1);
3588 /*-----------------------------------------------------------------*/
3589 /* geniCodeJumpTable - tries to create a jump table for switch */
3590 /*-----------------------------------------------------------------*/
3592 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3594 int min, max, cnt = 1;
3601 int needRangeCheck = !optimize.noJTabBoundary
3602 || tree->values.switchVals.swDefault;
3603 sym_link *cetype = getSpec (operandType (cond));
3604 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3605 int sizeofMatchJump, sizeofJumpTable;
3608 if (!tree || !caseVals)
3611 /* the criteria for creating a jump table is */
3612 /* all integer numbers between the maximum & minimum must */
3613 /* be present , the maximum value should not exceed 255 */
3614 /* If not all integer numbers are present the algorithm */
3615 /* inserts jumps to the default label for the missing numbers */
3616 /* and decides later whether it is worth it */
3617 min = (int) floatFromVal (vch = caseVals);
3624 max = (int) floatFromVal (vch);
3626 /* Exit if the range is too large to handle with a jump table. */
3627 if (1 + max - min > port->jumptableCost.maxCount)
3630 switch (getSize (operandType (cond)))
3632 case 1: sizeIndex = 0; break;
3633 case 2: sizeIndex = 1; break;
3634 case 4: sizeIndex = 2; break;
3638 /* Compute the size cost of the range check and subtraction. */
3640 sizeofZeroMinCost = 0;
3644 if (!(min==0 && IS_UNSIGNED (cetype)))
3645 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3646 if (!IS_UNSIGNED (cetype))
3647 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3648 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3651 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3653 /* If the size cost of handling a non-zero minimum exceeds the */
3654 /* cost of extending the range down to zero, then it might be */
3655 /* better to extend the range to zero. */
3656 if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3657 >= (min * port->jumptableCost.sizeofElement))
3659 /* Only extend the jump table if it would still be manageable. */
3660 if (1 + max <= port->jumptableCost.maxCount)
3663 if (IS_UNSIGNED (cetype))
3666 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3670 /* Compute the total size cost of a jump table. */
3671 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3672 + port->jumptableCost.sizeofDispatch
3673 + sizeofMinCost + sizeofMaxCost;
3675 /* Compute the total size cost of a match & jump sequence */
3676 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3678 /* If the size cost of the jump table is uneconomical then exit */
3679 if (sizeofMatchJump < sizeofJumpTable)
3682 /* The jump table is preferable. */
3684 /* First, a label for the default or missing cases. */
3685 if (tree->values.switchVals.swDefault)
3687 SNPRINTF (buffer, sizeof(buffer),
3689 tree->values.switchVals.swNum);
3693 SNPRINTF (buffer, sizeof(buffer),
3695 tree->values.switchVals.swNum);
3697 falseLabel = newiTempLabel (buffer);
3699 /* Build the list of labels for the jump table. */
3701 t = (int) floatFromVal (vch);
3702 for (i=min; i<=max; i++)
3706 /* Explicit case: make a new label for it. */
3707 SNPRINTF (buffer, sizeof(buffer),
3709 tree->values.switchVals.swNum,
3711 addSet (&labels, newiTempLabel (buffer));
3714 t = (int) floatFromVal (vch);
3718 /* Implicit case: use the default label. */
3719 addSet (&labels, falseLabel);
3723 /* first we rule out the boundary conditions */
3724 /* if only optimization says so */
3727 sym_link *cetype = getSpec (operandType (cond));
3728 /* no need to check the lower bound if
3729 the condition is unsigned & minimum value is zero */
3730 if (!(min == 0 && IS_UNSIGNED (cetype)))
3732 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3733 ic = newiCodeCondition (boundary, falseLabel, NULL);
3737 /* now for upper bounds */
3738 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3739 ic = newiCodeCondition (boundary, falseLabel, NULL);
3743 /* if the min is not zero then we no make it zero */
3746 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3747 if (!IS_LITERAL(getSpec(operandType(cond))))
3748 setOperandType (cond, UCHARTYPE);
3751 /* now create the jumptable */
3752 ic = newiCode (JUMPTABLE, NULL, NULL);
3753 IC_JTCOND (ic) = cond;
3754 IC_JTLABELS (ic) = labels;
3759 /*-----------------------------------------------------------------*/
3760 /* geniCodeSwitch - changes a switch to a if statement */
3761 /*-----------------------------------------------------------------*/
3763 geniCodeSwitch (ast * tree,int lvl)
3766 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3767 value *caseVals = tree->values.switchVals.swVals;
3768 symbol *trueLabel, *falseLabel;
3770 /* If the condition is a literal, then just jump to the */
3771 /* appropriate case label. */
3772 if (IS_LITERAL(getSpec(operandType(cond))))
3774 int switchVal, caseVal;
3776 switchVal = (int) floatFromVal (cond->operand.valOperand);
3779 caseVal = (int) floatFromVal (caseVals);
3780 if (caseVal == switchVal)
3782 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3783 tree->values.switchVals.swNum, caseVal);
3784 trueLabel = newiTempLabel (buffer);
3785 geniCodeGoto (trueLabel);
3788 caseVals = caseVals->next;
3790 goto defaultOrBreak;
3793 /* If cond is volatile, it might change while we are trying to */
3794 /* find the matching case. To avoid this possibility, make a */
3795 /* non-volatile copy to use instead. */
3796 if (IS_OP_VOLATILE (cond))
3801 newcond = newiTempOperand (operandType (cond), TRUE);
3802 newcond->isvolatile = 0;
3803 ic = newiCode ('=', NULL, cond);
3804 IC_RESULT (ic) = newcond;
3809 /* if we can make this a jump table */
3810 if (geniCodeJumpTable (cond, caseVals, tree))
3811 goto jumpTable; /* no need for the comparison */
3813 /* for the cases defined do */
3817 operand *compare = geniCodeLogic (cond,
3818 operandFromValue (caseVals),
3821 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3822 tree->values.switchVals.swNum,
3823 (int) floatFromVal (caseVals));
3824 trueLabel = newiTempLabel (buffer);
3826 ic = newiCodeCondition (compare, trueLabel, NULL);
3828 caseVals = caseVals->next;
3833 /* if default is present then goto break else break */
3834 if (tree->values.switchVals.swDefault)
3836 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3840 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3843 falseLabel = newiTempLabel (buffer);
3844 geniCodeGoto (falseLabel);
3847 ast2iCode (tree->right,lvl+1);
3850 /*-----------------------------------------------------------------*/
3851 /* geniCodeInline - intermediate code for inline assembler */
3852 /*-----------------------------------------------------------------*/
3854 geniCodeInline (ast * tree)
3858 ic = newiCode (INLINEASM, NULL, NULL);
3859 IC_INLINE (ic) = tree->values.inlineasm;
3863 /*-----------------------------------------------------------------*/
3864 /* geniCodeArrayInit - intermediate code for array initializer */
3865 /*-----------------------------------------------------------------*/
3867 geniCodeArrayInit (ast * tree, operand *array)
3871 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3872 ic = newiCode (ARRAYINIT, array, NULL);
3873 IC_ARRAYILIST (ic) = tree->values.constlist;
3875 operand *left=newOperand(), *right=newOperand();
3876 left->type=right->type=SYMBOL;
3877 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3878 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3879 ic = newiCode (ARRAYINIT, left, right);
3884 /*-----------------------------------------------------------------*/
3885 /* geniCodeCritical - intermediate code for a critical statement */
3886 /*-----------------------------------------------------------------*/
3888 geniCodeCritical (ast *tree, int lvl)
3894 if (!options.stackAuto)
3896 type = newLink(SPECIFIER);
3897 SPEC_VOLATILE(type) = 1;
3898 SPEC_NOUN(type) = V_BIT;
3899 SPEC_SCLS(type) = S_BIT;
3900 SPEC_BLEN(type) = 1;
3901 SPEC_BSTR(type) = 0;
3902 op = newiTempOperand(type, 1);
3905 /* If op is NULL, the original interrupt state will saved on */
3906 /* the stack. Otherwise, it will be saved in op. */
3908 /* Generate a save of the current interrupt state & disable */
3909 ic = newiCode (CRITICAL, NULL, NULL);
3910 IC_RESULT (ic) = op;
3913 /* Generate the critical code sequence */
3914 if (tree->left && tree->left->type == EX_VALUE)
3915 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3917 ast2iCode (tree->left,lvl+1);
3919 /* Generate a restore of the original interrupt state */
3920 ic = newiCode (ENDCRITICAL, NULL, op);
3924 /*-----------------------------------------------------------------*/
3925 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3926 /* particular case. Ie : assigning or dereferencing array or ptr */
3927 /*-----------------------------------------------------------------*/
3928 set * lvaluereqSet = NULL;
3929 typedef struct lvalItem
3936 /*-----------------------------------------------------------------*/
3937 /* addLvaluereq - add a flag for lvalreq for current ast level */
3938 /*-----------------------------------------------------------------*/
3939 void addLvaluereq(int lvl)
3941 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3944 addSetHead(&lvaluereqSet,lpItem);
3947 /*-----------------------------------------------------------------*/
3948 /* delLvaluereq - del a flag for lvalreq for current ast level */
3949 /*-----------------------------------------------------------------*/
3953 lpItem = getSet(&lvaluereqSet);
3954 if(lpItem) Safe_free(lpItem);
3956 /*-----------------------------------------------------------------*/
3957 /* clearLvaluereq - clear lvalreq flag */
3958 /*-----------------------------------------------------------------*/
3959 void clearLvaluereq()
3962 lpItem = peekSet(lvaluereqSet);
3963 if(lpItem) lpItem->req = 0;
3965 /*-----------------------------------------------------------------*/
3966 /* getLvaluereq - get the last lvalreq level */
3967 /*-----------------------------------------------------------------*/
3968 int getLvaluereqLvl()
3971 lpItem = peekSet(lvaluereqSet);
3972 if(lpItem) return lpItem->lvl;
3975 /*-----------------------------------------------------------------*/
3976 /* isLvaluereq - is lvalreq valid for this level ? */
3977 /*-----------------------------------------------------------------*/
3978 int isLvaluereq(int lvl)
3981 lpItem = peekSet(lvaluereqSet);
3982 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3986 /*-----------------------------------------------------------------*/
3987 /* ast2iCode - creates an icodeList from an ast */
3988 /*-----------------------------------------------------------------*/
3990 ast2iCode (ast * tree,int lvl)
3992 operand *left = NULL;
3993 operand *right = NULL;
3997 /* set the global variables for filename & line number */
3999 filename = tree->filename;
4001 lineno = tree->lineno;
4003 block = tree->block;
4005 scopeLevel = tree->level;
4007 seqPoint = tree->seqPoint;
4009 if (tree->type == EX_VALUE)
4010 return operandFromValue (tree->opval.val);
4012 if (tree->type == EX_LINK)
4013 return operandFromLink (tree->opval.lnk);
4015 /* if we find a nullop */
4016 if (tree->type == EX_OP &&
4017 (tree->opval.op == NULLOP ||
4018 tree->opval.op == BLOCK))
4020 if (tree->left && tree->left->type == EX_VALUE)
4021 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4023 ast2iCode (tree->left,lvl+1);
4024 if (tree->right && tree->right->type == EX_VALUE)
4025 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4027 ast2iCode (tree->right,lvl+1);
4031 /* special cases for not evaluating */
4032 if (tree->opval.op != ':' &&
4033 tree->opval.op != '?' &&
4034 tree->opval.op != CALL &&
4035 tree->opval.op != IFX &&
4036 tree->opval.op != AND_OP &&
4037 tree->opval.op != OR_OP &&
4038 tree->opval.op != LABEL &&
4039 tree->opval.op != GOTO &&
4040 tree->opval.op != SWITCH &&
4041 tree->opval.op != FUNCTION &&
4042 tree->opval.op != INLINEASM &&
4043 tree->opval.op != CRITICAL)
4046 if (IS_ASSIGN_OP (tree->opval.op) ||
4047 IS_DEREF_OP (tree) ||
4048 (tree->opval.op == '&' && !tree->right) ||
4049 tree->opval.op == PTR_OP)
4052 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4053 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4056 left = operandFromAst (tree->left,lvl);
4058 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4059 left = geniCodeRValue (left, TRUE);
4063 left = operandFromAst (tree->left,lvl);
4065 if (tree->opval.op == INC_OP ||
4066 tree->opval.op == DEC_OP)
4069 right = operandFromAst (tree->right,lvl);
4074 right = operandFromAst (tree->right,lvl);
4078 /* now depending on the type of operand */
4079 /* this will be a biggy */
4080 switch (tree->opval.op)
4083 case '[': /* array operation */
4085 //sym_link *ltype = operandType (left);
4086 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4087 left = geniCodeRValue (left, FALSE);
4088 right = geniCodeRValue (right, TRUE);
4091 return geniCodeArray (left, right,lvl);
4093 case '.': /* structure dereference */
4094 if (IS_PTR (operandType (left)))
4095 left = geniCodeRValue (left, TRUE);
4097 left = geniCodeRValue (left, FALSE);
4099 return geniCodeStruct (left, right, tree->lvalue);
4101 case PTR_OP: /* structure pointer dereference */
4104 pType = operandType (left);
4105 left = geniCodeRValue (left, TRUE);
4107 setOClass (pType, getSpec (operandType (left)));
4110 return geniCodeStruct (left, right, tree->lvalue);
4112 case INC_OP: /* increment operator */
4114 return geniCodePostInc (left);
4116 return geniCodePreInc (right, tree->lvalue);
4118 case DEC_OP: /* decrement operator */
4120 return geniCodePostDec (left);
4122 return geniCodePreDec (right, tree->lvalue);
4124 case '&': /* bitwise and or address of operator */
4126 { /* this is a bitwise operator */
4127 left = geniCodeRValue (left, FALSE);
4128 right = geniCodeRValue (right, FALSE);
4129 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4132 return geniCodeAddressOf (left);
4134 case '|': /* bitwise or & xor */
4136 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4137 geniCodeRValue (right, FALSE),
4142 return geniCodeDivision (geniCodeRValue (left, FALSE),
4143 geniCodeRValue (right, FALSE),
4144 getResultTypeFromType (tree->ftype));
4147 return geniCodeModulus (geniCodeRValue (left, FALSE),
4148 geniCodeRValue (right, FALSE),
4149 getResultTypeFromType (tree->ftype));
4152 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4153 geniCodeRValue (right, FALSE),
4154 getResultTypeFromType (tree->ftype));
4156 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4160 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4161 geniCodeRValue (right, FALSE),
4162 getResultTypeFromType (tree->ftype));
4164 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4168 return geniCodeAdd (geniCodeRValue (left, FALSE),
4169 geniCodeRValue (right, FALSE),
4170 getResultTypeFromType (tree->ftype),
4173 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4176 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4177 geniCodeRValue (right, FALSE),
4178 getResultTypeFromType (tree->ftype));
4181 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4182 geniCodeRValue (right, FALSE));
4184 #if 0 // this indeed needs a second thought
4188 // let's keep this simple: get the rvalue we need
4189 op=geniCodeRValue (right, FALSE);
4190 // now cast it to whatever we want
4191 op=geniCodeCast (operandType(left), op, FALSE);
4192 // if this is going to be used as an lvalue, make it so
4198 #else // bug #604575, is it a bug ????
4199 return geniCodeCast (operandType (left),
4200 geniCodeRValue (right, FALSE), FALSE);
4207 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4212 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4213 setOperandType (op, UCHARTYPE);
4220 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4221 geniCodeRValue (right, FALSE),
4223 setOperandType (op, (tree->opval.op == GETWORD) ? UINTTYPE : UCHARTYPE);
4228 return geniCodeLogicAndOr (tree, lvl);
4235 /* different compilers (even different gccs) evaluate
4236 the two calls in a different order. to get the same
4237 result on all machines we've to specify a clear sequence.
4238 return geniCodeLogic (geniCodeRValue (left, FALSE),
4239 geniCodeRValue (right, FALSE),
4243 operand *leftOp, *rightOp;
4245 leftOp = geniCodeRValue (left , FALSE);
4246 rightOp = geniCodeRValue (right, FALSE);
4248 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4251 return geniCodeConditional (tree,lvl);
4254 return operandFromLit (getSize (tree->right->ftype));
4258 sym_link *rtype = operandType (right);
4259 sym_link *ltype = operandType (left);
4260 if (IS_PTR (rtype) && IS_ITEMP (right)
4261 && right->isaddr && compareType (rtype->next, ltype) == 1)
4262 right = geniCodeRValue (right, TRUE);
4264 right = geniCodeRValue (right, FALSE);
4266 geniCodeAssign (left, right, 0, 1);
4271 geniCodeAssign (left,
4272 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4274 geniCodeRValue (right, FALSE),
4275 getResultTypeFromType (tree->ftype)),
4280 geniCodeAssign (left,
4281 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4283 geniCodeRValue (right, FALSE),
4284 getResultTypeFromType (tree->ftype)),
4288 geniCodeAssign (left,
4289 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4291 geniCodeRValue (right, FALSE),
4292 getResultTypeFromType (tree->ftype)),
4296 sym_link *rtype = operandType (right);
4297 sym_link *ltype = operandType (left);
4298 if (IS_PTR (rtype) && IS_ITEMP (right)
4299 && right->isaddr && compareType (rtype->next, ltype) == 1)
4300 right = geniCodeRValue (right, TRUE);
4302 right = geniCodeRValue (right, FALSE);
4305 return geniCodeAssign (left,
4306 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4309 getResultTypeFromType (tree->ftype),
4315 sym_link *rtype = operandType (right);
4316 sym_link *ltype = operandType (left);
4317 if (IS_PTR (rtype) && IS_ITEMP (right)
4318 && right->isaddr && compareType (rtype->next, ltype) == 1)
4320 right = geniCodeRValue (right, TRUE);
4324 right = geniCodeRValue (right, FALSE);
4327 geniCodeAssign (left,
4328 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4331 getResultTypeFromType (tree->ftype)),
4336 geniCodeAssign (left,
4337 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4339 geniCodeRValue (right, FALSE),
4340 getResultTypeFromType (tree->ftype)),
4344 geniCodeAssign (left,
4345 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4347 geniCodeRValue (right, FALSE)), 0, 1);
4350 geniCodeAssign (left,
4351 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4353 geniCodeRValue (right, FALSE),
4355 operandType (left)), 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);
4373 return geniCodeRValue (right, FALSE);
4376 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4379 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4380 return ast2iCode (tree->right,lvl+1);
4383 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4384 return ast2iCode (tree->right,lvl+1);
4387 geniCodeFunctionBody (tree,lvl);
4391 geniCodeReturn (right);
4395 geniCodeIfx (tree,lvl);
4399 geniCodeSwitch (tree,lvl);
4403 geniCodeInline (tree);
4407 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4411 geniCodeCritical (tree, lvl);
4417 /*-----------------------------------------------------------------*/
4418 /* reverseICChain - gets from the list and creates a linkedlist */
4419 /*-----------------------------------------------------------------*/
4426 while ((loop = getSet (&iCodeChain)))
4438 /*-----------------------------------------------------------------*/
4439 /* iCodeFromAst - given an ast will convert it to iCode */
4440 /*-----------------------------------------------------------------*/
4442 iCodeFromAst (ast * tree)
4444 returnLabel = newiTempLabel ("_return");
4445 entryLabel = newiTempLabel ("_entry");
4447 return reverseiCChain ();
4450 static const char *opTypeToStr(OPTYPE op)
4454 case SYMBOL: return "symbol";
4455 case VALUE: return "value";
4456 case TYPE: return "type";
4458 return "undefined type";
4462 operand *validateOpType(operand *op,
4469 if (op && op->type == type)
4474 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4475 " expected %s, got %s\n",
4476 macro, args, file, line,
4477 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4479 return op; // never reached, makes compiler happy.