1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 /*-----------------------------------------------------------------*/
30 /* global variables */
32 set *iCodeChain = NULL;
43 symbol *returnLabel; /* function return label */
44 symbol *entryLabel; /* function entry label */
46 /*-----------------------------------------------------------------*/
47 /* forward definition of some functions */
48 operand *geniCodeAssign (operand *, operand *, int, int);
49 static operand *geniCodeArray (operand *, operand *,int);
50 static operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
54 void setOClass (sym_link * ptr, sym_link * spec);
55 static operand *geniCodeCast (sym_link *, operand *, bool);
57 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
58 /* forward definition of ic print functions */
59 PRINTFUNC (picGetValueAtAddr);
60 PRINTFUNC (picSetValueAtAddr);
61 PRINTFUNC (picAddrOf);
62 PRINTFUNC (picGeneric);
63 PRINTFUNC (picGenericOne);
65 PRINTFUNC (picAssign);
69 PRINTFUNC (picJumpTable);
70 PRINTFUNC (picInline);
71 PRINTFUNC (picReceive);
72 PRINTFUNC (picDummyRead);
73 PRINTFUNC (picCritical);
74 PRINTFUNC (picEndCritical);
76 iCodeTable codeTable[] =
78 {'!', "not", picGenericOne, NULL},
79 {'~', "~", picGenericOne, NULL},
80 {RRC, "rrc", picGenericOne, NULL},
81 {RLC, "rlc", picGenericOne, NULL},
82 {GETHBIT, "ghbit", picGenericOne, NULL},
83 {UNARYMINUS, "-", picGenericOne, NULL},
84 {IPUSH, "push", picGenericOne, NULL},
85 {IPOP, "pop", picGenericOne, NULL},
86 {CALL, "call", picGenericOne, NULL},
87 {PCALL, "pcall", picGenericOne, NULL},
88 {FUNCTION, "proc", picGenericOne, NULL},
89 {ENDFUNCTION, "eproc", picGenericOne, NULL},
90 {RETURN, "ret", picGenericOne, NULL},
91 {'+', "+", picGeneric, NULL},
92 {'-', "-", picGeneric, NULL},
93 {'*', "*", picGeneric, NULL},
94 {'/', "/", picGeneric, NULL},
95 {'%', "%", picGeneric, NULL},
96 {'>', ">", picGeneric, NULL},
97 {'<', "<", picGeneric, NULL},
98 {LE_OP, "<=", picGeneric, NULL},
99 {GE_OP, ">=", picGeneric, NULL},
100 {EQ_OP, "==", picGeneric, NULL},
101 {NE_OP, "!=", picGeneric, NULL},
102 {AND_OP, "&&", picGeneric, NULL},
103 {OR_OP, "||", picGeneric, NULL},
104 {'^', "^", picGeneric, NULL},
105 {'|', "|", picGeneric, NULL},
106 {BITWISEAND, "&", picGeneric, NULL},
107 {LEFT_OP, "<<", picGeneric, NULL},
108 {RIGHT_OP, ">>", picGeneric, NULL},
109 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
110 {ADDRESS_OF, "&", picAddrOf, NULL},
111 {CAST, "<>", picCast, NULL},
112 {'=', ":=", picAssign, NULL},
113 {LABEL, "", picLabel, NULL},
114 {GOTO, "", picGoto, NULL},
115 {JUMPTABLE, "jtab", picJumpTable, NULL},
116 {IFX, "if", picIfx, NULL},
117 {INLINEASM, "", picInline, NULL},
118 {RECEIVE, "recv", picReceive, NULL},
119 {SEND, "send", picGenericOne, NULL},
120 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
121 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
122 {CRITICAL, "critical_start", picCritical, NULL},
123 {ENDCRITICAL, "critical_end", picEndCritical, NULL},
124 {SWAP, "swap", picGenericOne, NULL}
127 /*-----------------------------------------------------------------*/
128 /* checkConstantRange: check a constant against the type */
129 /*-----------------------------------------------------------------*/
132 /* pedantic=0: allmost anything is allowed as long as the absolute
133 value is within the bit range of the type, and -1 is treated as
134 0xf..f for unsigned types (e.g. in assign)
135 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
136 pedantic>1: "char c=200" is not allowed (evaluates to -56)
139 void checkConstantRange(sym_link *ltype, value *val, char *msg,
146 max = pow ((double)2.0, (double)bitsForType(ltype));
148 if (IS_LONG(val->type)) {
149 if (IS_UNSIGNED(val->type)) {
150 v=SPEC_CVAL(val->type).v_ulong;
152 v=SPEC_CVAL(val->type).v_long;
155 if (IS_UNSIGNED(val->type)) {
156 v=SPEC_CVAL(val->type).v_uint;
158 v=SPEC_CVAL(val->type).v_int;
164 // this could be a good idea
165 if (options.pedantic)
169 if (IS_FLOAT(ltype)) {
174 if (!IS_UNSIGNED(val->type) && v<0) {
176 if (IS_UNSIGNED(ltype) && (pedantic>1)) {
182 // if very pedantic: "char c=200" is not allowed
183 if (pedantic>1 && !IS_UNSIGNED(ltype)) {
184 max = max/2 + negative;
191 #if 0 // temporary disabled, leaving the warning as a reminder
193 SNPRINTF (message, sizeof(message), "for %s %s in %s",
194 IS_UNSIGNED(ltype) ? "unsigned" : "signed",
195 nounName(ltype), msg);
196 werror (W_CONST_RANGE, message);
204 /*-----------------------------------------------------------------*/
205 /* operandName - returns the name of the operand */
206 /*-----------------------------------------------------------------*/
208 printOperand (operand * op, FILE * file)
225 opetype = getSpec (operandType (op));
226 if (IS_FLOAT (opetype))
227 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
229 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
230 printTypeChain (operandType (op), file);
237 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}" , */
238 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
240 OP_LIVEFROM (op), OP_LIVETO (op),
241 OP_SYMBOL (op)->stack,
242 op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
243 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
244 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
248 printTypeChain (operandType (op), file);
249 if (SPIL_LOC (op) && IS_ITEMP (op))
250 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
255 /* if assigned to registers */
256 if (OP_SYMBOL (op)->nRegs)
258 if (OP_SYMBOL (op)->isspilt)
260 if (!OP_SYMBOL (op)->remat)
261 if (OP_SYMBOL (op)->usl.spillLoc)
262 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
263 OP_SYMBOL (op)->usl.spillLoc->rname :
264 OP_SYMBOL (op)->usl.spillLoc->name));
266 fprintf (file, "[err]");
268 fprintf (file, "[remat]");
274 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
275 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
280 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
281 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
282 /* if assigned to registers */
283 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
287 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
288 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
289 OP_SYMBOL (op)->regs[i]->name :
298 printTypeChain (op->operand.typeOperand, file);
304 fprintf (file, "\n");
309 /*-----------------------------------------------------------------*/
310 /* print functions */
311 /*-----------------------------------------------------------------*/
312 PRINTFUNC (picGetValueAtAddr)
315 printOperand (IC_RESULT (ic), of);
318 printOperand (IC_LEFT (ic), of);
324 PRINTFUNC (picSetValueAtAddr)
328 printOperand (IC_LEFT (ic), of);
329 fprintf (of, "] = ");
330 printOperand (IC_RIGHT (ic), of);
334 PRINTFUNC (picAddrOf)
337 printOperand (IC_RESULT (ic), of);
338 if (IS_ITEMP (IC_LEFT (ic)))
341 fprintf (of, " = &[");
342 printOperand (IC_LEFT (ic), of);
345 if (IS_ITEMP (IC_LEFT (ic)))
346 fprintf (of, " offsetAdd ");
349 printOperand (IC_RIGHT (ic), of);
351 if (IS_ITEMP (IC_LEFT (ic)))
357 PRINTFUNC (picJumpTable)
362 fprintf (of, "%s\t", s);
363 printOperand (IC_JTCOND (ic), of);
365 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
366 sym = setNextItem (IC_JTLABELS (ic)))
367 fprintf (of, "\t\t\t%s\n", sym->name);
370 PRINTFUNC (picGeneric)
373 printOperand (IC_RESULT (ic), of);
375 printOperand (IC_LEFT (ic), of);
376 fprintf (of, " %s ", s);
377 printOperand (IC_RIGHT (ic), of);
381 PRINTFUNC (picGenericOne)
386 printOperand (IC_RESULT (ic), of);
392 fprintf (of, "%s ", s);
393 printOperand (IC_LEFT (ic), of);
396 if (!IC_RESULT (ic) && !IC_LEFT (ic))
399 if (ic->op == SEND || ic->op == RECEIVE) {
400 fprintf(of,"{argreg = %d}",ic->argreg);
408 printOperand (IC_RESULT (ic), of);
410 printOperand (IC_LEFT (ic), of);
411 printOperand (IC_RIGHT (ic), of);
416 PRINTFUNC (picAssign)
420 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
423 printOperand (IC_RESULT (ic), of);
425 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
428 fprintf (of, " %s ", s);
429 printOperand (IC_RIGHT (ic), of);
436 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
442 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
449 printOperand (IC_COND (ic), of);
452 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
455 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
457 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
461 PRINTFUNC (picInline)
463 fprintf (of, "%s", IC_INLINE (ic));
466 PRINTFUNC (picReceive)
468 printOperand (IC_RESULT (ic), of);
469 fprintf (of, " = %s ", s);
470 printOperand (IC_LEFT (ic), of);
474 PRINTFUNC (picDummyRead)
477 fprintf (of, "%s ", s);
478 printOperand (IC_RIGHT (ic), of);
482 PRINTFUNC (picCritical)
486 printOperand (IC_RESULT (ic), of);
488 fprintf (of, "(stack)");
489 fprintf (of, " = %s ", s);
493 PRINTFUNC (picEndCritical)
496 fprintf (of, "%s = ", s);
498 printOperand (IC_RIGHT (ic), of);
500 fprintf (of, "(stack)");
504 /*-----------------------------------------------------------------*/
505 /* piCode - prints one iCode */
506 /*-----------------------------------------------------------------*/
508 piCode (void *item, FILE * of)
516 icTab = getTableEntry (ic->op);
517 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
518 ic->filename, ic->lineno,
519 ic->seq, ic->key, ic->depth, ic->supportRtn);
520 icTab->iCodePrint (of, ic, icTab->printName);
526 printiCChain(ic,stdout);
528 /*-----------------------------------------------------------------*/
529 /* printiCChain - prints intermediate code for humans */
530 /*-----------------------------------------------------------------*/
532 printiCChain (iCode * icChain, FILE * of)
539 for (loop = icChain; loop; loop = loop->next)
541 if ((icTab = getTableEntry (loop->op)))
543 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
544 loop->filename, loop->lineno,
545 loop->seq, loop->key, loop->depth, loop->supportRtn);
547 icTab->iCodePrint (of, loop, icTab->printName);
553 /*-----------------------------------------------------------------*/
554 /* newOperand - allocate, init & return a new iCode */
555 /*-----------------------------------------------------------------*/
561 op = Safe_alloc ( sizeof (operand));
567 /*-----------------------------------------------------------------*/
568 /* newiCode - create and return a new iCode entry initialised */
569 /*-----------------------------------------------------------------*/
571 newiCode (int op, operand * left, operand * right)
575 ic = Safe_alloc ( sizeof (iCode));
577 ic->seqPoint = seqPoint;
579 ic->filename = filename;
581 ic->level = scopeLevel;
583 ic->key = iCodeKey++;
585 IC_RIGHT (ic) = right;
590 /*-----------------------------------------------------------------*/
591 /* newiCode for conditional statements */
592 /*-----------------------------------------------------------------*/
594 newiCodeCondition (operand * condition,
600 if (IS_VOID(operandType(condition))) {
601 werror(E_VOID_VALUE_USED);
604 ic = newiCode (IFX, NULL, NULL);
605 IC_COND (ic) = condition;
606 IC_TRUE (ic) = trueLabel;
607 IC_FALSE (ic) = falseLabel;
611 /*-----------------------------------------------------------------*/
612 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
613 /*-----------------------------------------------------------------*/
615 newiCodeLabelGoto (int op, symbol * label)
619 ic = newiCode (op, NULL, NULL);
623 IC_RIGHT (ic) = NULL;
624 IC_RESULT (ic) = NULL;
628 /*-----------------------------------------------------------------*/
629 /* newiTemp - allocate & return a newItemp Variable */
630 /*-----------------------------------------------------------------*/
638 SNPRINTF (buffer, sizeof(buffer), "%s", s);
642 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
645 itmp = newSymbol (buffer, 1);
646 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
652 /*-----------------------------------------------------------------*/
653 /* newiTempLabel - creates a temp variable label */
654 /*-----------------------------------------------------------------*/
656 newiTempLabel (char *s)
660 /* check if this alredy exists */
661 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
666 itmplbl = newSymbol (s, 1);
670 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
671 itmplbl = newSymbol (buffer, 1);
676 itmplbl->key = labelKey++;
677 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
681 /*-----------------------------------------------------------------*/
682 /* newiTempPreheaderLabel - creates a new preheader label */
683 /*-----------------------------------------------------------------*/
685 newiTempPreheaderLabel ()
689 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
690 itmplbl = newSymbol (buffer, 1);
694 itmplbl->key = labelKey++;
695 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
700 /*-----------------------------------------------------------------*/
701 /* initiCode - initialises some iCode related stuff */
702 /*-----------------------------------------------------------------*/
709 /*-----------------------------------------------------------------*/
710 /* copyiCode - make a copy of the iCode given */
711 /*-----------------------------------------------------------------*/
713 copyiCode (iCode * ic)
715 iCode *nic = newiCode (ic->op, NULL, NULL);
717 nic->lineno = ic->lineno;
718 nic->filename = ic->filename;
719 nic->block = ic->block;
720 nic->level = ic->level;
721 nic->parmBytes = ic->parmBytes;
723 /* deal with the special cases first */
727 IC_COND (nic) = operandFromOperand (IC_COND (ic));
728 IC_TRUE (nic) = IC_TRUE (ic);
729 IC_FALSE (nic) = IC_FALSE (ic);
733 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
734 IC_JTLABELS (nic) = IC_JTLABELS (ic);
739 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
740 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
744 IC_INLINE (nic) = IC_INLINE (ic);
748 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
752 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
753 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
754 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
760 /*-----------------------------------------------------------------*/
761 /* getTableEntry - gets the table entry for the given operator */
762 /*-----------------------------------------------------------------*/
764 getTableEntry (int oper)
768 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
769 if (oper == codeTable[i].icode)
770 return &codeTable[i];
775 /*-----------------------------------------------------------------*/
776 /* newiTempOperand - new intermediate temp operand */
777 /*-----------------------------------------------------------------*/
779 newiTempOperand (sym_link * type, char throwType)
782 operand *op = newOperand ();
786 itmp = newiTemp (NULL);
788 etype = getSpec (type);
790 if (IS_LITERAL (etype))
793 /* copy the type information */
795 itmp->etype = getSpec (itmp->type = (throwType ? type :
796 copyLinkChain (type)));
797 if (IS_LITERAL (itmp->etype))
799 SPEC_SCLS (itmp->etype) = S_REGISTER;
800 SPEC_OCLS (itmp->etype) = reg;
803 op->operand.symOperand = itmp;
804 op->key = itmp->key = ++operandKey;
808 /*-----------------------------------------------------------------*/
809 /* operandType - returns the type chain for an operand */
810 /*-----------------------------------------------------------------*/
812 operandType (operand * op)
814 /* depending on type of operand */
819 return op->operand.valOperand->type;
822 return op->operand.symOperand->type;
825 return op->operand.typeOperand;
827 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
828 " operand type not known ");
829 assert (0); /* should never come here */
830 /* Just to keep the compiler happy */
831 return (sym_link *) 0;
835 /*-----------------------------------------------------------------*/
836 /* isParamterToCall - will return 1 if op is a parameter to args */
837 /*-----------------------------------------------------------------*/
839 isParameterToCall (value * args, operand * op)
843 wassert (IS_SYMOP(op));
848 isSymbolEqual (op->operand.symOperand, tval->sym))
855 /*-----------------------------------------------------------------*/
856 /* isOperandGlobal - return 1 if operand is a global variable */
857 /*-----------------------------------------------------------------*/
859 isOperandGlobal (operand * op)
868 (op->operand.symOperand->level == 0 ||
869 IS_STATIC (op->operand.symOperand->etype) ||
870 IS_EXTERN (op->operand.symOperand->etype))
877 /*-----------------------------------------------------------------*/
878 /* isOperandVolatile - return 1 if the operand is volatile */
879 /*-----------------------------------------------------------------*/
881 isOperandVolatile (operand * op, bool chkTemp)
886 if (IS_ITEMP (op) && !chkTemp)
889 opetype = getSpec (optype = operandType (op));
891 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
894 if (IS_VOLATILE (opetype))
899 /*-----------------------------------------------------------------*/
900 /* isOperandLiteral - returns 1 if an operand contains a literal */
901 /*-----------------------------------------------------------------*/
903 isOperandLiteral (operand * op)
910 opetype = getSpec (operandType (op));
912 if (IS_LITERAL (opetype))
918 /*-----------------------------------------------------------------*/
919 /* isOperandInFarSpace - will return true if operand is in farSpace */
920 /*-----------------------------------------------------------------*/
922 isOperandInFarSpace (operand * op)
932 if (!IS_TRUE_SYMOP (op))
935 etype = SPIL_LOC (op)->etype;
941 etype = getSpec (operandType (op));
943 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
946 /*------------------------------------------------------------------*/
947 /* isOperandInDirSpace - will return true if operand is in dirSpace */
948 /*------------------------------------------------------------------*/
950 isOperandInDirSpace (operand * op)
960 if (!IS_TRUE_SYMOP (op))
963 etype = SPIL_LOC (op)->etype;
969 etype = getSpec (operandType (op));
971 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
974 /*--------------------------------------------------------------------*/
975 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
976 /*--------------------------------------------------------------------*/
978 isOperandInCodeSpace (operand * op)
988 etype = getSpec (operandType (op));
990 if (!IS_TRUE_SYMOP (op))
993 etype = SPIL_LOC (op)->etype;
999 etype = getSpec (operandType (op));
1001 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1004 /*-----------------------------------------------------------------*/
1005 /* isOperandOnStack - will return true if operand is on stack */
1006 /*-----------------------------------------------------------------*/
1008 isOperandOnStack (operand * op)
1018 etype = getSpec (operandType (op));
1019 if (IN_STACK (etype) ||
1020 OP_SYMBOL(op)->onStack ||
1021 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1027 /*-----------------------------------------------------------------*/
1028 /* isOclsExpensive - will return true if accesses to an output */
1029 /* storage class are expensive */
1030 /*-----------------------------------------------------------------*/
1032 isOclsExpensive (struct memmap *oclass)
1034 if (port->oclsExpense)
1035 return port->oclsExpense (oclass) > 0;
1037 /* In the absence of port specific guidance, assume only */
1038 /* farspace is expensive. */
1039 return IN_FARSPACE (oclass);
1042 /*-----------------------------------------------------------------*/
1043 /* operandLitValue - literal value of an operand */
1044 /*-----------------------------------------------------------------*/
1046 operandLitValue (operand * op)
1048 assert (isOperandLiteral (op));
1050 return floatFromVal (op->operand.valOperand);
1053 /*-----------------------------------------------------------------*/
1054 /* getBuiltInParms - returns parameters to a builtin functions */
1055 /*-----------------------------------------------------------------*/
1056 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1061 /* builtin functions uses only SEND for parameters */
1062 while (ic->op != CALL) {
1063 assert(ic->op == SEND && ic->builtinSEND);
1064 ic->generated = 1; /* mark the icode as generated */
1065 parms[*pcount] = IC_LEFT(ic);
1071 /* make sure this is a builtin function call */
1072 assert(IS_SYMOP(IC_LEFT(ic)));
1073 ftype = operandType(IC_LEFT(ic));
1074 assert(IFFUNC_ISBUILTIN(ftype));
1078 /*-----------------------------------------------------------------*/
1079 /* operandOperation - performs operations on operands */
1080 /*-----------------------------------------------------------------*/
1082 operandOperation (operand * left, operand * right,
1083 int op, sym_link * type)
1085 sym_link *let , *ret=NULL;
1086 operand *retval = (operand *) 0;
1088 assert (isOperandLiteral (left));
1089 let = getSpec(operandType(left));
1091 assert (isOperandLiteral (right));
1092 ret = getSpec(operandType(right));
1098 retval = operandFromValue (valCastLiteral (type,
1099 operandLitValue (left) +
1100 operandLitValue (right)));
1103 retval = operandFromValue (valCastLiteral (type,
1104 operandLitValue (left) -
1105 operandLitValue (right)));
1109 retval = operandFromValue (valCastLiteral (type,
1110 operandLitValue (left) *
1111 operandLitValue (right)));
1112 This could be all we've to do, but with gcc we've to take care about
1113 overflows. Two examples:
1114 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1115 significant bits are lost (52 in fraction, 63 bits would be
1116 necessary to keep full precision).
1117 If the resulting double value is greater than ULONG_MAX (resp.
1118 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1121 /* if it is not a specifier then we can assume that */
1122 /* it will be an unsigned long */
1123 if (IS_INT (type) ||
1126 /* long is handled here, because it can overflow with double */
1127 if (IS_LONG (type) ||
1129 /* signed and unsigned mul are the same, as long as the precision
1130 of the result isn't bigger than the precision of the operands. */
1131 retval = operandFromValue (valCastLiteral (type,
1132 (TYPE_UDWORD) operandLitValue (left) *
1133 (TYPE_UDWORD) operandLitValue (right)));
1134 else if (IS_UNSIGNED (type)) /* unsigned int */
1136 /* unsigned int is handled here in order to detect overflow */
1137 TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
1138 (TYPE_UWORD) operandLitValue (right);
1140 retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
1141 if (ul != (TYPE_UWORD) ul)
1144 else /* signed int */
1146 /* signed int is handled here in order to detect overflow */
1147 TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
1148 (TYPE_WORD) operandLitValue (right);
1150 retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
1151 if (l != (TYPE_WORD) l)
1156 /* all others go here: */
1157 retval = operandFromValue (valCastLiteral (type,
1158 operandLitValue (left) *
1159 operandLitValue (right)));
1162 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1164 werror (E_DIVIDE_BY_ZERO);
1170 if (IS_UNSIGNED (type))
1172 SPEC_USIGN (let) = 1;
1173 SPEC_USIGN (ret) = 1;
1174 retval = operandFromValue (valCastLiteral (type,
1175 (TYPE_UDWORD) operandLitValue (left) /
1176 (TYPE_UDWORD) operandLitValue (right)));
1180 retval = operandFromValue (valCastLiteral (type,
1181 operandLitValue (left) /
1182 operandLitValue (right)));
1187 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1189 werror (E_DIVIDE_BY_ZERO);
1194 if (IS_UNSIGNED (type))
1195 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1196 (TYPE_UDWORD) operandLitValue (right));
1198 retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1199 (TYPE_DWORD) operandLitValue (right));
1203 /* The number of left shifts is always unsigned. Signed doesn't make
1204 sense here. Shifting by a negative number is impossible. */
1205 retval = operandFromValue (valCastLiteral (type,
1206 ((TYPE_UDWORD) operandLitValue (left) <<
1207 (TYPE_UDWORD) operandLitValue (right))));
1210 /* The number of right shifts is always unsigned. Signed doesn't make
1211 sense here. Shifting by a negative number is impossible. */
1212 if (IS_UNSIGNED(let))
1213 /* unsigned: logic shift right */
1214 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1215 (TYPE_UDWORD) operandLitValue (right));
1217 /* signed: arithmetic shift right */
1218 retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1219 (TYPE_UDWORD) operandLitValue (right));
1222 if (IS_FLOAT (let) ||
1225 retval = operandFromLit (operandLitValue (left) ==
1226 operandLitValue (right));
1230 /* this op doesn't care about signedness */
1233 l = (TYPE_UDWORD) operandLitValue (left);
1234 r = (TYPE_UDWORD) operandLitValue (right);
1235 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1236 neccessary to strip them to 16 bit.
1237 Literals are reduced to their cheapest type, therefore left and
1238 right might have different types. It's neccessary to find a
1239 common type: int (used for char too) or long */
1240 if (!IS_LONG (let) &&
1246 retval = operandFromLit (l == r);
1250 retval = operandFromLit (operandLitValue (left) <
1251 operandLitValue (right));
1254 retval = operandFromLit (operandLitValue (left) <=
1255 operandLitValue (right));
1258 retval = operandFromLit (operandLitValue (left) !=
1259 operandLitValue (right));
1262 retval = operandFromLit (operandLitValue (left) >
1263 operandLitValue (right));
1266 retval = operandFromLit (operandLitValue (left) >=
1267 operandLitValue (right));
1270 retval = operandFromValue (valCastLiteral (type,
1271 (TYPE_UDWORD)operandLitValue(left) &
1272 (TYPE_UDWORD)operandLitValue(right)));
1275 retval = operandFromValue (valCastLiteral (type,
1276 (TYPE_UDWORD)operandLitValue(left) |
1277 (TYPE_UDWORD)operandLitValue(right)));
1280 retval = operandFromValue (valCastLiteral (type,
1281 (TYPE_UDWORD)operandLitValue(left) ^
1282 (TYPE_UDWORD)operandLitValue(right)));
1285 retval = operandFromLit (operandLitValue (left) &&
1286 operandLitValue (right));
1289 retval = operandFromLit (operandLitValue (left) ||
1290 operandLitValue (right));
1294 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1296 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1302 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1304 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1310 retval = operandFromValue (valCastLiteral (type,
1311 -1 * operandLitValue (left)));
1315 retval = operandFromValue (valCastLiteral (type,
1317 operandLitValue (left))));
1321 retval = operandFromLit (!operandLitValue (left));
1325 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1326 " operandOperation invalid operator ");
1334 /*-----------------------------------------------------------------*/
1335 /* isOperandEqual - compares two operand & return 1 if they r = */
1336 /*-----------------------------------------------------------------*/
1338 isOperandEqual (operand * left, operand * right)
1340 /* if the pointers are equal then they are equal */
1344 /* if either of them null then false */
1345 if (!left || !right)
1348 if (left->type != right->type)
1351 if (IS_SYMOP (left) && IS_SYMOP (right))
1352 return left->key == right->key;
1354 /* if types are the same */
1358 return isSymbolEqual (left->operand.symOperand,
1359 right->operand.symOperand);
1361 return (floatFromVal (left->operand.valOperand) ==
1362 floatFromVal (right->operand.valOperand));
1364 if (compareType (left->operand.typeOperand,
1365 right->operand.typeOperand) == 1)
1372 /*-------------------------------------------------------------------*/
1373 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1374 /*-------------------------------------------------------------------*/
1376 isiCodeEqual (iCode * left, iCode * right)
1378 /* if the same pointer */
1382 /* if either of them null */
1383 if (!left || !right)
1386 /* if operand are the same */
1387 if (left->op == right->op)
1390 /* compare all the elements depending on type */
1391 if (left->op != IFX)
1393 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1395 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1401 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1403 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1405 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1414 /*-----------------------------------------------------------------*/
1415 /* newiTempFromOp - create a temp Operand with same attributes */
1416 /*-----------------------------------------------------------------*/
1418 newiTempFromOp (operand * op)
1428 nop = newiTempOperand (operandType (op), TRUE);
1429 nop->isaddr = op->isaddr;
1430 nop->isvolatile = op->isvolatile;
1431 nop->isGlobal = op->isGlobal;
1432 nop->isLiteral = op->isLiteral;
1433 nop->usesDefs = op->usesDefs;
1434 nop->isParm = op->isParm;
1438 /*-----------------------------------------------------------------*/
1439 /* operand from operand - creates an operand holder for the type */
1440 /*-----------------------------------------------------------------*/
1442 operandFromOperand (operand * op)
1448 nop = newOperand ();
1449 nop->type = op->type;
1450 nop->isaddr = op->isaddr;
1452 nop->isvolatile = op->isvolatile;
1453 nop->isGlobal = op->isGlobal;
1454 nop->isLiteral = op->isLiteral;
1455 nop->usesDefs = op->usesDefs;
1456 nop->isParm = op->isParm;
1461 nop->operand.symOperand = op->operand.symOperand;
1464 nop->operand.valOperand = op->operand.valOperand;
1467 nop->operand.typeOperand = op->operand.typeOperand;
1474 /*-----------------------------------------------------------------*/
1475 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1476 /*-----------------------------------------------------------------*/
1478 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1480 operand *nop = operandFromOperand (op);
1482 if (nop->type == SYMBOL)
1484 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1485 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1491 /*-----------------------------------------------------------------*/
1492 /* operandFromSymbol - creates an operand from a symbol */
1493 /*-----------------------------------------------------------------*/
1495 operandFromSymbol (symbol * sym)
1500 /* if the symbol's type is a literal */
1501 /* then it is an enumerator type */
1502 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1503 return operandFromValue (valFromType (sym->etype));
1506 sym->key = ++operandKey;
1508 /* if this an implicit variable, means struct/union */
1509 /* member so just return it */
1510 if (sym->implicit || IS_FUNC (sym->type))
1514 op->operand.symOperand = sym;
1516 op->isvolatile = isOperandVolatile (op, TRUE);
1517 op->isGlobal = isOperandGlobal (op);
1521 /* under the following conditions create a
1522 register equivalent for a local symbol */
1523 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1524 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1526 (!(options.model == MODEL_FLAT24)) ) &&
1527 options.stackAuto == 0)
1530 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1531 !IS_FUNC (sym->type) && /* not a function */
1532 !sym->_isparm && /* not a parameter */
1533 IS_AUTO (sym) && /* is a local auto variable */
1534 !sym->addrtaken && /* whose address has not been taken */
1535 !sym->reqv && /* does not already have a reg equivalence */
1536 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1537 !sym->islbl && /* not a label */
1538 ok && /* farspace check */
1539 !IS_BITVAR (sym->etype) /* not a bit variable */
1543 /* we will use it after all optimizations
1544 and before liveRange calculation */
1545 sym->reqv = newiTempOperand (sym->type, 0);
1546 sym->reqv->key = sym->key;
1547 OP_SYMBOL (sym->reqv)->prereqv = sym;
1548 OP_SYMBOL (sym->reqv)->key = sym->key;
1549 OP_SYMBOL (sym->reqv)->isreqv = 1;
1550 OP_SYMBOL (sym->reqv)->islocal = 1;
1551 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1552 SPIL_LOC (sym->reqv) = sym;
1555 if (!IS_AGGREGATE (sym->type))
1559 op->operand.symOperand = sym;
1562 op->isvolatile = isOperandVolatile (op, TRUE);
1563 op->isGlobal = isOperandGlobal (op);
1564 op->isPtr = IS_PTR (operandType (op));
1565 op->isParm = sym->_isparm;
1570 /* itemp = &[_symbol] */
1572 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1573 IC_LEFT (ic)->type = SYMBOL;
1574 IC_LEFT (ic)->operand.symOperand = sym;
1575 IC_LEFT (ic)->key = sym->key;
1576 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1577 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1578 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1581 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1582 if (IS_ARRAY (sym->type))
1584 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1585 IC_RESULT (ic)->isaddr = 0;
1588 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1592 return IC_RESULT (ic);
1595 /*-----------------------------------------------------------------*/
1596 /* operandFromValue - creates an operand from value */
1597 /*-----------------------------------------------------------------*/
1599 operandFromValue (value * val)
1603 /* if this is a symbol then do the symbol thing */
1605 return operandFromSymbol (val->sym);
1607 /* this is not a symbol */
1610 op->operand.valOperand = val;
1611 op->isLiteral = isOperandLiteral (op);
1615 /*-----------------------------------------------------------------*/
1616 /* operandFromLink - operand from typeChain */
1617 /*-----------------------------------------------------------------*/
1619 operandFromLink (sym_link * type)
1623 /* operand from sym_link */
1629 op->operand.typeOperand = copyLinkChain (type);
1633 /*-----------------------------------------------------------------*/
1634 /* operandFromLit - makes an operand from a literal value */
1635 /*-----------------------------------------------------------------*/
1637 operandFromLit (double i)
1639 return operandFromValue (valueFromLit (i));
1642 /*-----------------------------------------------------------------*/
1643 /* operandFromAst - creates an operand from an ast */
1644 /*-----------------------------------------------------------------*/
1646 operandFromAst (ast * tree,int lvl)
1652 /* depending on type do */
1656 return ast2iCode (tree,lvl+1);
1660 return operandFromValue (tree->opval.val);
1664 return operandFromLink (tree->opval.lnk);
1671 /* Just to keep the compiler happy */
1672 return (operand *) 0;
1675 /*-----------------------------------------------------------------*/
1676 /* setOperandType - sets the operand's type to the given type */
1677 /*-----------------------------------------------------------------*/
1679 setOperandType (operand * op, sym_link * type)
1681 /* depending on the type of operand */
1686 op->operand.valOperand->etype =
1687 getSpec (op->operand.valOperand->type =
1688 copyLinkChain (type));
1692 if (op->operand.symOperand->isitmp)
1693 op->operand.symOperand->etype =
1694 getSpec (op->operand.symOperand->type =
1695 copyLinkChain (type));
1697 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1698 "attempt to modify type of source");
1702 op->operand.typeOperand = copyLinkChain (type);
1708 /*-----------------------------------------------------------------*/
1709 /* Get size in byte of ptr need to access an array */
1710 /*-----------------------------------------------------------------*/
1712 getArraySizePtr (operand * op)
1714 sym_link *ltype = operandType(op);
1718 int size = getSize(ltype);
1719 return(IS_GENPTR(ltype)?(size-1):size);
1724 sym_link *letype = getSpec(ltype);
1725 switch (PTR_TYPE (SPEC_OCLS (letype)))
1737 return (GPTRSIZE-1);
1746 /*-----------------------------------------------------------------*/
1747 /* perform "usual unary conversions" */
1748 /*-----------------------------------------------------------------*/
1751 usualUnaryConversions (operand * op)
1753 if (IS_INTEGRAL (operandType (op)))
1755 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1758 return geniCodeCast (INTTYPE, op, TRUE);
1765 /*-----------------------------------------------------------------*/
1766 /* perform "usual binary conversions" */
1767 /*-----------------------------------------------------------------*/
1770 usualBinaryConversions (operand ** op1, operand ** op2,
1771 RESULT_TYPE resultType, int op)
1774 sym_link *rtype = operandType (*op2);
1775 sym_link *ltype = operandType (*op1);
1777 ctype = computeType (ltype, rtype, resultType, op);
1784 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1786 /* one byte operations: keep signedness for code generator */
1794 *op1 = geniCodeCast (ctype, *op1, TRUE);
1795 *op2 = geniCodeCast (ctype, *op2, TRUE);
1800 /*-----------------------------------------------------------------*/
1801 /* geniCodeValueAtAddress - generate intermeditate code for value */
1803 /*-----------------------------------------------------------------*/
1805 geniCodeRValue (operand * op, bool force)
1808 sym_link *type = operandType (op);
1809 sym_link *etype = getSpec (type);
1811 /* if this is an array & already */
1812 /* an address then return this */
1813 if (IS_AGGREGATE (type) ||
1814 (IS_PTR (type) && !force && !op->isaddr))
1815 return operandFromOperand (op);
1817 /* if this is not an address then must be */
1818 /* rvalue already so return this one */
1822 /* if this is not a temp symbol then */
1823 if (!IS_ITEMP (op) &&
1825 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1827 op = operandFromOperand (op);
1832 if (IS_SPEC (type) &&
1833 IS_TRUE_SYMOP (op) &&
1834 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1835 (options.model == MODEL_FLAT24) ))
1837 op = operandFromOperand (op);
1842 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1843 if (IS_PTR (type) && op->isaddr && force)
1846 type = copyLinkChain (type);
1848 IC_RESULT (ic) = newiTempOperand (type, 1);
1849 IC_RESULT (ic)->isaddr = 0;
1851 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1855 return IC_RESULT (ic);
1858 /*-----------------------------------------------------------------*/
1859 /* geniCodeCast - changes the value from one type to another */
1860 /*-----------------------------------------------------------------*/
1862 geniCodeCast (sym_link * type, operand * op, bool implicit)
1866 sym_link *opetype = getSpec (optype = operandType (op));
1870 /* one of them has size zero then error */
1871 if (IS_VOID (optype))
1873 werror (E_CAST_ZERO);
1877 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1879 geniCodeArray2Ptr (op);
1883 /* if the operand is already the desired type then do nothing */
1884 if (compareType (type, optype) == 1)
1887 /* if this is a literal then just change the type & return */
1888 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1890 return operandFromValue (valCastLiteral (type,
1891 operandLitValue (op)));
1894 /* if casting to/from pointers, do some checking */
1895 if (IS_PTR(type)) { // to a pointer
1896 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1897 if (IS_INTEGRAL(optype)) {
1898 // maybe this is NULL, than it's ok.
1899 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1900 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1901 // no way to set the storage
1902 if (IS_LITERAL(optype)) {
1903 werror(E_LITERAL_GENERIC);
1906 werror(E_NONPTR2_GENPTR);
1909 } else if (implicit) {
1910 werror(W_INTEGRAL2PTR_NOCAST);
1915 // shouldn't do that with float, array or structure unless to void
1916 if (!IS_VOID(getSpec(type)) &&
1917 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1918 werror(E_INCOMPAT_TYPES);
1922 } else { // from a pointer to a pointer
1923 if (IS_GENPTR(type) && IS_VOID(type->next))
1924 { // cast to void* is always allowed
1926 else if (IS_GENPTR(optype) && IS_VOID(optype->next))
1927 { // cast from void* is always allowed
1929 else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
1930 // if not a pointer to a function
1931 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1932 if (implicit) { // if not to generic, they have to match
1933 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1934 werror(E_INCOMPAT_PTYPES);
1941 } else { // to a non pointer
1942 if (IS_PTR(optype)) { // from a pointer
1943 if (implicit) { // sneaky
1944 if (IS_INTEGRAL(type)) {
1945 werror(W_PTR2INTEGRAL_NOCAST);
1947 } else { // shouldn't do that with float, array or structure
1948 werror(E_INCOMPAT_TYPES);
1955 printFromToType (optype, type);
1958 /* if they are the same size create an assignment */
1960 /* This seems very dangerous to me, since there are several */
1961 /* optimizations (for example, gcse) that don't notice the */
1962 /* cast hidden in this assignement and may simplify an */
1963 /* iCode to use the original (uncasted) operand. */
1964 /* Unfortunately, other things break when this cast is */
1965 /* made explicit. Need to fix this someday. */
1966 /* -- EEP, 2004/01/21 */
1967 if (getSize (type) == getSize (optype) &&
1968 !IS_BITFIELD (type) &&
1970 !IS_FLOAT (optype) &&
1971 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1972 (!IS_SPEC (type) && !IS_SPEC (optype))))
1974 ic = newiCode ('=', NULL, op);
1975 IC_RESULT (ic) = newiTempOperand (type, 0);
1976 SPIL_LOC (IC_RESULT (ic)) =
1977 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1978 IC_RESULT (ic)->isaddr = 0;
1982 ic = newiCode (CAST, operandFromLink (type),
1983 geniCodeRValue (op, FALSE));
1985 IC_RESULT (ic) = newiTempOperand (type, 0);
1988 /* preserve the storage class & output class */
1989 /* of the original variable */
1990 restype = getSpec (operandType (IC_RESULT (ic)));
1991 if (!IS_LITERAL(opetype) &&
1993 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1994 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1997 return IC_RESULT (ic);
2000 /*-----------------------------------------------------------------*/
2001 /* geniCodeLabel - will create a Label */
2002 /*-----------------------------------------------------------------*/
2004 geniCodeLabel (symbol * label)
2008 ic = newiCodeLabelGoto (LABEL, label);
2012 /*-----------------------------------------------------------------*/
2013 /* geniCodeGoto - will create a Goto */
2014 /*-----------------------------------------------------------------*/
2016 geniCodeGoto (symbol * label)
2020 ic = newiCodeLabelGoto (GOTO, label);
2024 /*-----------------------------------------------------------------*/
2025 /* geniCodeMultiply - gen intermediate code for multiplication */
2026 /*-----------------------------------------------------------------*/
2028 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2035 /* if they are both literal then we know the result */
2036 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2037 return operandFromValue (valMult (left->operand.valOperand,
2038 right->operand.valOperand));
2040 if (IS_LITERAL(retype)) {
2041 p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2044 resType = usualBinaryConversions (&left, &right, resultType, '*');
2046 rtype = operandType (right);
2047 retype = getSpec (rtype);
2048 ltype = operandType (left);
2049 letype = getSpec (ltype);
2052 /* if the right is a literal & power of 2 */
2053 /* then make it a left shift */
2054 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2055 efficient in most cases than 2 bytes result = 2 bytes << literal
2056 if port has 1 byte muldiv */
2057 if (p2 && !IS_FLOAT (letype)
2058 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2059 && (port->support.muldiv == 1))
2060 && strcmp (port->target, "pic14") != 0 /* don't shift for pic */
2061 && strcmp (port->target, "pic16") != 0)
2063 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2065 /* LEFT_OP need same size for left and result, */
2066 left = geniCodeCast (resType, left, TRUE);
2067 ltype = operandType (left);
2069 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2073 ic = newiCode ('*', left, right); /* normal multiplication */
2074 /* if the size left or right > 1 then support routine */
2075 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2079 IC_RESULT (ic) = newiTempOperand (resType, 1);
2082 return IC_RESULT (ic);
2085 /*-----------------------------------------------------------------*/
2086 /* geniCodeDivision - gen intermediate code for division */
2087 /*-----------------------------------------------------------------*/
2089 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2094 sym_link *rtype = operandType (right);
2095 sym_link *retype = getSpec (rtype);
2096 sym_link *ltype = operandType (left);
2097 sym_link *letype = getSpec (ltype);
2099 resType = usualBinaryConversions (&left, &right, resultType, '/');
2101 /* if the right is a literal & power of 2
2102 and left is unsigned then make it a
2104 if (IS_LITERAL (retype) &&
2105 !IS_FLOAT (letype) &&
2106 IS_UNSIGNED(letype) &&
2107 (p2 = powof2 ((TYPE_UDWORD)
2108 floatFromVal (right->operand.valOperand)))) {
2109 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2113 ic = newiCode ('/', left, right); /* normal division */
2114 /* if the size left or right > 1 then support routine */
2115 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2118 IC_RESULT (ic) = newiTempOperand (resType, 0);
2121 return IC_RESULT (ic);
2123 /*-----------------------------------------------------------------*/
2124 /* geniCodeModulus - gen intermediate code for modulus */
2125 /*-----------------------------------------------------------------*/
2127 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2133 /* if they are both literal then we know the result */
2134 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2135 return operandFromValue (valMod (left->operand.valOperand,
2136 right->operand.valOperand));
2138 resType = usualBinaryConversions (&left, &right, resultType, '%');
2140 /* now they are the same size */
2141 ic = newiCode ('%', left, right);
2143 /* if the size left or right > 1 then support routine */
2144 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2146 IC_RESULT (ic) = newiTempOperand (resType, 0);
2149 return IC_RESULT (ic);
2152 /*-----------------------------------------------------------------*/
2153 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2154 /*-----------------------------------------------------------------*/
2156 geniCodePtrPtrSubtract (operand * left, operand * right)
2162 /* if they are both literals then */
2163 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2165 result = operandFromValue (valMinus (left->operand.valOperand,
2166 right->operand.valOperand));
2170 ic = newiCode ('-', left, right);
2172 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2176 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2180 // should we really do this? is this ANSI?
2181 return geniCodeDivision (result,
2182 operandFromLit (getSize (ltype->next)),
2186 /*-----------------------------------------------------------------*/
2187 /* geniCodeSubtract - generates code for subtraction */
2188 /*-----------------------------------------------------------------*/
2190 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2197 /* if they both pointers then */
2198 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2199 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2200 return geniCodePtrPtrSubtract (left, right);
2202 /* if they are both literal then we know the result */
2203 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2204 && left->isLiteral && right->isLiteral)
2205 return operandFromValue (valMinus (left->operand.valOperand,
2206 right->operand.valOperand));
2208 /* if left is an array or pointer */
2209 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2211 isarray = left->isaddr;
2212 right = geniCodeMultiply (right,
2213 operandFromLit (getSize (ltype->next)),
2214 (getArraySizePtr(left) >= INTSIZE) ?
2217 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2220 { /* make them the same size */
2221 resType = usualBinaryConversions (&left, &right, resultType, '-');
2224 ic = newiCode ('-', left, right);
2226 IC_RESULT (ic) = newiTempOperand (resType, 1);
2227 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2229 /* if left or right is a float */
2230 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2234 return IC_RESULT (ic);
2237 /*-----------------------------------------------------------------*/
2238 /* geniCodeAdd - generates iCode for addition */
2239 /*-----------------------------------------------------------------*/
2241 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2250 /* if the right side is LITERAL zero */
2251 /* return the left side */
2252 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2255 /* if left is literal zero return right */
2256 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2259 /* if left is a pointer then size */
2260 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2262 isarray = left->isaddr;
2263 // there is no need to multiply with 1
2264 if (getSize (ltype->next) != 1)
2266 size = operandFromLit (getSize (ltype->next));
2267 SPEC_USIGN (getSpec (operandType (size))) = 1;
2268 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2269 right = geniCodeMultiply (right,
2271 (getArraySizePtr(left) >= INTSIZE) ?
2274 /* Even if right is a 'unsigned char',
2275 the result will be a 'signed int' due to the promotion rules.
2276 It doesn't make sense when accessing arrays, so let's fix it here: */
2278 SPEC_USIGN (getSpec (operandType (right))) = 1;
2280 resType = copyLinkChain (ltype);
2283 { // make them the same size
2284 resType = usualBinaryConversions (&left, &right, resultType, '+');
2287 /* if they are both literals then we know */
2288 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2289 && left->isLiteral && right->isLiteral)
2290 return operandFromValue (valPlus (valFromType (ltype),
2291 valFromType (rtype)));
2293 ic = newiCode ('+', left, right);
2295 IC_RESULT (ic) = newiTempOperand (resType, 1);
2296 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2298 /* if left or right is a float then support
2300 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2305 return IC_RESULT (ic);
2309 /*-----------------------------------------------------------------*/
2310 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2311 /*-----------------------------------------------------------------*/
2313 aggrToPtr (sym_link * type, bool force)
2318 if (IS_PTR (type) && !force)
2321 etype = getSpec (type);
2322 ptype = newLink (DECLARATOR);
2326 /* set the pointer depending on the storage class */
2327 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2331 /*------------------------------------------------------------------*/
2332 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2333 /*------------------------------------------------------------------*/
2335 aggrToPtrDclType (sym_link * type, bool force)
2337 if (IS_PTR (type) && !force)
2338 return DCL_TYPE (type);
2340 /* return the pointer depending on the storage class */
2341 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2344 /*-----------------------------------------------------------------*/
2345 /* geniCodeArray2Ptr - array to pointer */
2346 /*-----------------------------------------------------------------*/
2348 geniCodeArray2Ptr (operand * op)
2350 sym_link *optype = operandType (op);
2351 sym_link *opetype = getSpec (optype);
2353 /* set the pointer depending on the storage class */
2354 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2361 /*-----------------------------------------------------------------*/
2362 /* geniCodeArray - array access */
2363 /*-----------------------------------------------------------------*/
2365 geniCodeArray (operand * left, operand * right, int lvl)
2369 sym_link *ltype = operandType (left);
2374 if (IS_PTR (ltype->next) && left->isaddr)
2376 left = geniCodeRValue (left, FALSE);
2379 return geniCodeDerefPtr (geniCodeAdd (left,
2381 (getArraySizePtr(left) >= INTSIZE) ?
2387 size = operandFromLit (getSize (ltype->next));
2388 SPEC_USIGN (getSpec (operandType (size))) = 1;
2389 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2390 right = geniCodeMultiply (right,
2392 (getArraySizePtr(left) >= INTSIZE) ?
2395 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2396 It doesn't make sense when accessing arrays, so let's fix it here: */
2398 SPEC_USIGN (getSpec (operandType (right))) = 1;
2399 /* we can check for limits here */
2400 /* already done in SDCCast.c
2401 if (isOperandLiteral (right) &&
2404 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2406 werror (W_IDX_OUT_OF_BOUNDS,
2407 (int) operandLitValue (right) / getSize (ltype->next),
2412 ic = newiCode ('+', left, right);
2414 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2415 !IS_AGGREGATE (ltype->next) &&
2416 !IS_PTR (ltype->next))
2417 ? ltype : ltype->next), 0);
2419 if (!IS_AGGREGATE (ltype->next))
2421 IC_RESULT (ic)->isaddr = 1;
2422 IC_RESULT (ic)->aggr2ptr = 1;
2426 return IC_RESULT (ic);
2429 /*-----------------------------------------------------------------*/
2430 /* geniCodeStruct - generates intermediate code for structures */
2431 /*-----------------------------------------------------------------*/
2433 geniCodeStruct (operand * left, operand * right, bool islval)
2436 sym_link *type = operandType (left);
2437 sym_link *etype = getSpec (type);
2439 symbol *element = getStructElement (SPEC_STRUCT (etype),
2440 right->operand.symOperand);
2442 wassert(IS_SYMOP(right));
2444 /* add the offset */
2445 ic = newiCode ('+', left, operandFromLit (element->offset));
2447 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2449 /* preserve the storage & output class of the struct */
2450 /* as well as the volatile attribute */
2451 retype = getSpec (operandType (IC_RESULT (ic)));
2452 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2453 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2454 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2455 SPEC_CONST (retype) |= SPEC_CONST (etype);
2457 if (IS_PTR (element->type))
2458 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2460 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2463 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2466 /*-----------------------------------------------------------------*/
2467 /* geniCodePostInc - generate int code for Post increment */
2468 /*-----------------------------------------------------------------*/
2470 geniCodePostInc (operand * op)
2474 sym_link *optype = operandType (op);
2476 operand *rv = (IS_ITEMP (op) ?
2477 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2479 sym_link *rvtype = operandType (rv);
2482 /* if this is not an address we have trouble */
2485 werror (E_LVALUE_REQUIRED, "++");
2489 rOp = newiTempOperand (rvtype, 0);
2490 OP_SYMBOL(rOp)->noSpilLoc = 1;
2493 OP_SYMBOL(rv)->noSpilLoc = 1;
2495 geniCodeAssign (rOp, rv, 0, 0);
2497 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2499 werror(W_SIZEOF_VOID);
2500 if (IS_FLOAT (rvtype))
2501 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2503 ic = newiCode ('+', rv, operandFromLit (size));
2505 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2508 geniCodeAssign (op, result, 0, 0);
2514 /*-----------------------------------------------------------------*/
2515 /* geniCodePreInc - generate code for preIncrement */
2516 /*-----------------------------------------------------------------*/
2518 geniCodePreInc (operand * op, bool lvalue)
2521 sym_link *optype = operandType (op);
2522 operand *rop = (IS_ITEMP (op) ?
2523 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2525 sym_link *roptype = operandType (rop);
2531 werror (E_LVALUE_REQUIRED, "++");
2535 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2537 werror(W_SIZEOF_VOID);
2538 if (IS_FLOAT (roptype))
2539 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2541 ic = newiCode ('+', rop, operandFromLit (size));
2542 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2545 (void) geniCodeAssign (op, result, 0, 0);
2546 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2552 /*-----------------------------------------------------------------*/
2553 /* geniCodePostDec - generates code for Post decrement */
2554 /*-----------------------------------------------------------------*/
2556 geniCodePostDec (operand * op)
2560 sym_link *optype = operandType (op);
2562 operand *rv = (IS_ITEMP (op) ?
2563 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2565 sym_link *rvtype = operandType (rv);
2568 /* if this is not an address we have trouble */
2571 werror (E_LVALUE_REQUIRED, "--");
2575 rOp = newiTempOperand (rvtype, 0);
2576 OP_SYMBOL(rOp)->noSpilLoc = 1;
2579 OP_SYMBOL(rv)->noSpilLoc = 1;
2581 geniCodeAssign (rOp, rv, 0, 0);
2583 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2585 werror(W_SIZEOF_VOID);
2586 if (IS_FLOAT (rvtype))
2587 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2589 ic = newiCode ('-', rv, operandFromLit (size));
2591 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2594 geniCodeAssign (op, result, 0, 0);
2600 /*-----------------------------------------------------------------*/
2601 /* geniCodePreDec - generate code for pre decrement */
2602 /*-----------------------------------------------------------------*/
2604 geniCodePreDec (operand * op, bool lvalue)
2607 sym_link *optype = operandType (op);
2608 operand *rop = (IS_ITEMP (op) ?
2609 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2611 sym_link *roptype = operandType (rop);
2617 werror (E_LVALUE_REQUIRED, "--");
2621 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2623 werror(W_SIZEOF_VOID);
2624 if (IS_FLOAT (roptype))
2625 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2627 ic = newiCode ('-', rop, operandFromLit (size));
2628 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2631 (void) geniCodeAssign (op, result, 0, 0);
2632 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2639 /*-----------------------------------------------------------------*/
2640 /* geniCodeBitwise - gen int code for bitWise operators */
2641 /*-----------------------------------------------------------------*/
2643 geniCodeBitwise (operand * left, operand * right,
2644 int oper, sym_link * resType)
2648 left = geniCodeCast (resType, left, TRUE);
2649 right = geniCodeCast (resType, right, TRUE);
2651 ic = newiCode (oper, left, right);
2652 IC_RESULT (ic) = newiTempOperand (resType, 0);
2655 return IC_RESULT (ic);
2658 /*-----------------------------------------------------------------*/
2659 /* geniCodeAddressOf - gens icode for '&' address of operator */
2660 /*-----------------------------------------------------------------*/
2662 geniCodeAddressOf (operand * op)
2666 sym_link *optype = operandType (op);
2667 sym_link *opetype = getSpec (optype);
2669 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2671 op = operandFromOperand (op);
2676 /* lvalue check already done in decorateType */
2677 /* this must be a lvalue */
2678 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2679 /* werror (E_LVALUE_REQUIRED,"&"); */
2683 p = newLink (DECLARATOR);
2685 /* set the pointer depending on the storage class */
2686 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2688 p->next = copyLinkChain (optype);
2690 /* if already a temp */
2693 setOperandType (op, p);
2698 /* other wise make this of the type coming in */
2699 ic = newiCode (ADDRESS_OF, op, NULL);
2700 IC_RESULT (ic) = newiTempOperand (p, 1);
2701 IC_RESULT (ic)->isaddr = 0;
2703 return IC_RESULT (ic);
2705 /*-----------------------------------------------------------------*/
2706 /* setOClass - sets the output class depending on the pointer type */
2707 /*-----------------------------------------------------------------*/
2709 setOClass (sym_link * ptr, sym_link * spec)
2711 switch (DCL_TYPE (ptr))
2714 SPEC_OCLS (spec) = data;
2718 SPEC_OCLS (spec) = generic;
2722 SPEC_OCLS (spec) = xdata;
2726 SPEC_OCLS (spec) = code;
2730 SPEC_OCLS (spec) = idata;
2734 SPEC_OCLS (spec) = xstack;
2738 SPEC_OCLS (spec) = eeprom;
2747 /*-----------------------------------------------------------------*/
2748 /* geniCodeDerefPtr - dereference pointer with '*' */
2749 /*-----------------------------------------------------------------*/
2751 geniCodeDerefPtr (operand * op,int lvl)
2753 sym_link *rtype, *retype;
2754 sym_link *optype = operandType (op);
2756 // if this is an array then array access
2757 if (IS_ARRAY (optype)) {
2758 // don't worry, this will be optimized out later
2759 return geniCodeArray (op, operandFromLit (0), lvl);
2762 // just in case someone screws up
2763 wassert (IS_PTR (optype));
2765 if (IS_TRUE_SYMOP (op))
2768 op = geniCodeRValue (op, TRUE);
2771 /* now get rid of the pointer part */
2772 if (isLvaluereq(lvl) && IS_ITEMP (op))
2774 retype = getSpec (rtype = copyLinkChain (optype));
2778 retype = getSpec (rtype = copyLinkChain (optype->next));
2779 /* outputclass needs 2b updated */
2780 setOClass (optype, retype);
2783 op->isGptr = IS_GENPTR (optype);
2785 op->isaddr = (IS_PTR (rtype) ||
2786 IS_STRUCT (rtype) ||
2791 if (!isLvaluereq(lvl))
2792 op = geniCodeRValue (op, TRUE);
2794 setOperandType (op, rtype);
2799 /*-----------------------------------------------------------------*/
2800 /* geniCodeUnaryMinus - does a unary minus of the operand */
2801 /*-----------------------------------------------------------------*/
2803 geniCodeUnaryMinus (operand * op)
2806 sym_link *optype = operandType (op);
2808 if (IS_LITERAL (optype))
2809 return operandFromLit (-floatFromVal (op->operand.valOperand));
2811 ic = newiCode (UNARYMINUS, op, NULL);
2812 IC_RESULT (ic) = newiTempOperand (optype, 0);
2814 return IC_RESULT (ic);
2817 /*-----------------------------------------------------------------*/
2818 /* geniCodeLeftShift - gen i code for left shift */
2819 /*-----------------------------------------------------------------*/
2821 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2826 ic = newiCode (LEFT_OP, left, right);
2828 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2829 IC_RESULT (ic) = newiTempOperand (resType, 0);
2831 return IC_RESULT (ic);
2834 /*-----------------------------------------------------------------*/
2835 /* geniCodeRightShift - gen i code for right shift */
2836 /*-----------------------------------------------------------------*/
2838 geniCodeRightShift (operand * left, operand * right)
2842 ic = newiCode (RIGHT_OP, left, right);
2843 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2845 return IC_RESULT (ic);
2848 /*-----------------------------------------------------------------*/
2849 /* geniCodeLogic- logic code */
2850 /*-----------------------------------------------------------------*/
2852 geniCodeLogic (operand * left, operand * right, int op)
2856 sym_link *rtype = operandType (right);
2857 sym_link *ltype = operandType (left);
2859 /* left is integral type and right is literal then
2860 check if the literal value is within bounds */
2861 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2863 checkConstantRange(ltype,
2864 OP_VALUE(right), "compare operation", 1);
2867 /* if one operand is a pointer and the other is a literal generic void pointer,
2868 change the type of the literal generic void pointer to match the other pointer */
2869 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2870 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2872 /* find left's definition */
2873 ic = (iCode *) setFirstItem (iCodeChain);
2876 if (((ic->op == CAST) || (ic->op == '='))
2877 && isOperandEqual(left, IC_RESULT (ic)))
2880 ic = setNextItem (iCodeChain);
2882 /* if casting literal to generic pointer, then cast to rtype instead */
2883 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2885 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2886 ltype = operandType(left);
2889 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2890 && IS_PTR (ltype) && !IS_GENPTR(ltype))
2892 /* find right's definition */
2893 ic = (iCode *) setFirstItem (iCodeChain);
2896 if (((ic->op == CAST) || (ic->op == '='))
2897 && isOperandEqual(right, IC_RESULT (ic)))
2900 ic = setNextItem (iCodeChain);
2902 /* if casting literal to generic pointer, then cast to rtype instead */
2903 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2905 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2906 rtype = operandType(right);
2910 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
2912 ic = newiCode (op, left, right);
2913 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2915 /* if comparing float
2916 and not a '==' || '!=' || '&&' || '||' (these
2918 if (IS_FLOAT(ctype) &&
2926 return IC_RESULT (ic);
2929 /*-----------------------------------------------------------------*/
2930 /* geniCodeLogicAndOr - && || operations */
2931 /*-----------------------------------------------------------------*/
2933 geniCodeLogicAndOr (ast *tree, int lvl)
2936 symbol *falseLabel = newiTempLabel (NULL);
2937 symbol *trueLabel = newiTempLabel (NULL);
2938 symbol *exitLabel = newiTempLabel (NULL);
2939 operand *op, *result, *condition;
2941 /* AND_OP and OR_OP are no longer generated because of bug-905492.
2942 They can be reenabled by executing the following block. If you find
2943 a decent optimization you could start right here:
2948 operand *leftOp, *rightOp;
2950 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
2951 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
2953 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
2957 /* generate two IFX for the '&&' or '||' op */
2959 /* evaluate left operand */
2960 condition = ast2iCode (tree->left, lvl + 1);
2961 op = geniCodeRValue (condition, FALSE);
2963 /* test left operand */
2964 if (tree->opval.op == AND_OP)
2965 ic = newiCodeCondition (op, NULL, falseLabel);
2967 ic = newiCodeCondition (op, trueLabel, NULL);
2970 /* evaluate right operand */
2971 condition = ast2iCode (tree->right, lvl + 1);
2972 op = geniCodeRValue (condition, FALSE);
2974 /* test right operand */
2975 ic = newiCodeCondition (op, trueLabel, NULL);
2978 /* store 0 or 1 in result */
2979 result = newiTempOperand (newCharLink(), 1);
2981 geniCodeLabel (falseLabel);
2982 geniCodeAssign (result, operandFromLit (0), 0, 0);
2983 /* generate an unconditional goto */
2984 geniCodeGoto (exitLabel);
2986 geniCodeLabel (trueLabel);
2987 geniCodeAssign (result, operandFromLit (1), 0, 0);
2989 geniCodeLabel (exitLabel);
2994 /*-----------------------------------------------------------------*/
2995 /* geniCodeUnary - for a a generic unary operation */
2996 /*-----------------------------------------------------------------*/
2998 geniCodeUnary (operand * op, int oper)
3000 iCode *ic = newiCode (oper, op, NULL);
3002 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3004 return IC_RESULT (ic);
3007 /*-----------------------------------------------------------------*/
3008 /* geniCodeConditional - geniCode for '?' ':' operation */
3009 /*-----------------------------------------------------------------*/
3011 geniCodeConditional (ast * tree,int lvl)
3014 symbol *falseLabel = newiTempLabel (NULL);
3015 symbol *exitLabel = newiTempLabel (NULL);
3016 operand *cond = ast2iCode (tree->left,lvl+1);
3017 operand *true, *false, *result;
3019 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3023 true = ast2iCode (tree->right->left,lvl+1);
3025 /* move the value to a new Operand */
3026 result = newiTempOperand (tree->right->ftype, 0);
3027 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3029 /* generate an unconditional goto */
3030 geniCodeGoto (exitLabel);
3032 /* now for the right side */
3033 geniCodeLabel (falseLabel);
3035 false = ast2iCode (tree->right->right,lvl+1);
3036 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3038 /* create the exit label */
3039 geniCodeLabel (exitLabel);
3044 /*-----------------------------------------------------------------*/
3045 /* geniCodeAssign - generate code for assignment */
3046 /*-----------------------------------------------------------------*/
3048 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3051 sym_link *ltype = operandType (left);
3052 sym_link *rtype = operandType (right);
3054 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3056 werror (E_LVALUE_REQUIRED, "assignment");
3060 /* left is integral type and right is literal then
3061 check if the literal value is within bounds */
3062 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3064 checkConstantRange(ltype,
3065 OP_VALUE(right), "= operation", 0);
3068 /* if the left & right type don't exactly match */
3069 /* if pointer set then make sure the check is
3070 done with the type & not the pointer */
3071 /* then cast rights type to left */
3073 /* first check the type for pointer assignement */
3074 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3075 compareType (ltype, rtype) <= 0)
3077 if (compareType (ltype->next, rtype) < 0)
3078 right = geniCodeCast (ltype->next, right, TRUE);
3080 else if (compareType (ltype, rtype) < 0)
3081 right = geniCodeCast (ltype, right, TRUE);
3083 /* If left is a true symbol & ! volatile
3084 create an assignment to temporary for
3085 the right & then assign this temporary
3086 to the symbol. This is SSA (static single
3087 assignment). Isn't it simple and folks have
3088 published mountains of paper on it */
3089 if (IS_TRUE_SYMOP (left) &&
3090 !isOperandVolatile (left, FALSE) &&
3091 isOperandGlobal (left))
3095 if (IS_TRUE_SYMOP (right))
3096 sym = OP_SYMBOL (right);
3097 ic = newiCode ('=', NULL, right);
3098 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3099 SPIL_LOC (right) = sym;
3103 ic = newiCode ('=', NULL, right);
3104 IC_RESULT (ic) = left;
3107 /* if left isgptr flag is set then support
3108 routine will be required */
3112 ic->nosupdate = nosupdate;
3116 /*-----------------------------------------------------------------*/
3117 /* geniCodeDummyRead - generate code for dummy read */
3118 /*-----------------------------------------------------------------*/
3120 geniCodeDummyRead (operand * op)
3123 sym_link *type = operandType (op);
3125 if (!IS_VOLATILE(type))
3128 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3134 /*-----------------------------------------------------------------*/
3135 /* geniCodeSEParms - generate code for side effecting fcalls */
3136 /*-----------------------------------------------------------------*/
3138 geniCodeSEParms (ast * parms,int lvl)
3143 if (parms->type == EX_OP && parms->opval.op == PARAM)
3145 geniCodeSEParms (parms->left,lvl);
3146 geniCodeSEParms (parms->right,lvl);
3150 /* hack don't like this but too lazy to think of
3152 if (IS_ADDRESS_OF_OP (parms))
3153 parms->left->lvalue = 1;
3155 if (IS_CAST_OP (parms) &&
3156 IS_PTR (parms->ftype) &&
3157 IS_ADDRESS_OF_OP (parms->right))
3158 parms->right->left->lvalue = 1;
3160 parms->opval.oprnd =
3161 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3163 parms->type = EX_OPERAND;
3164 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3165 SPEC_ARGREG(parms->ftype);
3168 /*-----------------------------------------------------------------*/
3169 /* geniCodeParms - generates parameters */
3170 /*-----------------------------------------------------------------*/
3172 geniCodeParms (ast * parms, value *argVals, int *stack,
3173 sym_link * ftype, int lvl)
3181 if (argVals==NULL) {
3183 argVals = FUNC_ARGS (ftype);
3186 /* if this is a param node then do the left & right */
3187 if (parms->type == EX_OP && parms->opval.op == PARAM)
3189 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3190 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3194 /* get the parameter value */
3195 if (parms->type == EX_OPERAND)
3196 pval = parms->opval.oprnd;
3199 /* maybe this else should go away ?? */
3200 /* hack don't like this but too lazy to think of
3202 if (IS_ADDRESS_OF_OP (parms))
3203 parms->left->lvalue = 1;
3205 if (IS_CAST_OP (parms) &&
3206 IS_PTR (parms->ftype) &&
3207 IS_ADDRESS_OF_OP (parms->right))
3208 parms->right->left->lvalue = 1;
3210 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3213 /* if register parm then make it a send */
3214 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3215 IFFUNC_ISBUILTIN(ftype))
3217 ic = newiCode (SEND, pval, NULL);
3218 ic->argreg = SPEC_ARGREG(parms->etype);
3219 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3224 /* now decide whether to push or assign */
3225 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3229 operand *top = operandFromSymbol (argVals->sym);
3230 /* clear useDef and other bitVectors */
3231 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3232 geniCodeAssign (top, pval, 1, 0);
3236 sym_link *p = operandType (pval);
3238 ic = newiCode (IPUSH, pval, NULL);
3240 /* update the stack adjustment */
3241 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3246 argVals=argVals->next;
3250 /*-----------------------------------------------------------------*/
3251 /* geniCodeCall - generates temp code for calling */
3252 /*-----------------------------------------------------------------*/
3254 geniCodeCall (operand * left, ast * parms,int lvl)
3258 sym_link *type, *etype;
3262 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3263 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3264 werror (E_FUNCTION_EXPECTED);
3265 return operandFromValue(valueFromLit(0));
3268 /* take care of parameters with side-effecting
3269 function calls in them, this is required to take care
3270 of overlaying function parameters */
3271 geniCodeSEParms (parms,lvl);
3273 ftype = operandType (left);
3274 if (IS_CODEPTR (ftype))
3275 ftype = ftype->next;
3277 /* first the parameters */
3278 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3280 /* now call : if symbol then pcall */
3281 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3282 ic = newiCode (PCALL, left, NULL);
3284 ic = newiCode (CALL, left, NULL);
3287 type = copyLinkChain (ftype->next);
3288 etype = getSpec (type);
3289 SPEC_EXTR (etype) = 0;
3290 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3294 /* stack adjustment after call */
3295 ic->parmBytes = stack;
3300 /*-----------------------------------------------------------------*/
3301 /* geniCodeReceive - generate intermediate code for "receive" */
3302 /*-----------------------------------------------------------------*/
3304 geniCodeReceive (value * args)
3306 /* for all arguments that are passed in registers */
3310 if (IS_REGPARM (args->etype))
3312 operand *opr = operandFromValue (args);
3314 symbol *sym = OP_SYMBOL (opr);
3317 /* we will use it after all optimizations
3318 and before liveRange calculation */
3319 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3322 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3323 options.stackAuto == 0 &&
3324 (!(options.model == MODEL_FLAT24)) )
3329 opl = newiTempOperand (args->type, 0);
3331 sym->reqv->key = sym->key;
3332 OP_SYMBOL (sym->reqv)->key = sym->key;
3333 OP_SYMBOL (sym->reqv)->isreqv = 1;
3334 OP_SYMBOL (sym->reqv)->islocal = 0;
3335 SPIL_LOC (sym->reqv) = sym;
3339 ic = newiCode (RECEIVE, NULL, NULL);
3340 ic->argreg = SPEC_ARGREG(args->etype);
3342 currFunc->recvSize = getSize (sym->type);
3345 IC_RESULT (ic) = opr;
3353 /*-----------------------------------------------------------------*/
3354 /* geniCodeFunctionBody - create the function body */
3355 /*-----------------------------------------------------------------*/
3357 geniCodeFunctionBody (ast * tree,int lvl)
3364 /* reset the auto generation */
3370 func = ast2iCode (tree->left,lvl+1);
3371 fetype = getSpec (operandType (func));
3373 savelineno = lineno;
3374 lineno = OP_SYMBOL (func)->lineDef;
3375 /* create an entry label */
3376 geniCodeLabel (entryLabel);
3377 lineno = savelineno;
3379 /* create a proc icode */
3380 ic = newiCode (FUNCTION, func, NULL);
3381 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3386 /* for all parameters that are passed
3387 on registers add a "receive" */
3388 geniCodeReceive (tree->values.args);
3390 /* generate code for the body */
3391 ast2iCode (tree->right,lvl+1);
3393 /* create a label for return */
3394 geniCodeLabel (returnLabel);
3396 /* now generate the end proc */
3397 ic = newiCode (ENDFUNCTION, func, NULL);
3403 /*-----------------------------------------------------------------*/
3404 /* geniCodeReturn - gen icode for 'return' statement */
3405 /*-----------------------------------------------------------------*/
3407 geniCodeReturn (operand * op)
3411 /* if the operand is present force an rvalue */
3413 op = geniCodeRValue (op, FALSE);
3415 ic = newiCode (RETURN, op, NULL);
3419 /*-----------------------------------------------------------------*/
3420 /* geniCodeIfx - generates code for extended if statement */
3421 /*-----------------------------------------------------------------*/
3423 geniCodeIfx (ast * tree,int lvl)
3426 operand *condition = ast2iCode (tree->left,lvl+1);
3429 /* if condition is null then exit */
3433 condition = geniCodeRValue (condition, FALSE);
3435 cetype = getSpec (operandType (condition));
3436 /* if the condition is a literal */
3437 if (IS_LITERAL (cetype))
3439 if (floatFromVal (condition->operand.valOperand))
3441 if (tree->trueLabel)
3442 geniCodeGoto (tree->trueLabel);
3448 if (tree->falseLabel)
3449 geniCodeGoto (tree->falseLabel);
3456 if (tree->trueLabel)
3458 ic = newiCodeCondition (condition,
3463 if (tree->falseLabel)
3464 geniCodeGoto (tree->falseLabel);
3468 ic = newiCodeCondition (condition,
3475 ast2iCode (tree->right,lvl+1);
3478 /*-----------------------------------------------------------------*/
3479 /* geniCodeJumpTable - tries to create a jump table for switch */
3480 /*-----------------------------------------------------------------*/
3482 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3484 int min, max, cnt = 1;
3491 int needRangeCheck = !optimize.noJTabBoundary
3492 || tree->values.switchVals.swDefault;
3493 sym_link *cetype = getSpec (operandType (cond));
3494 int sizeofMinCost, sizeofMaxCost;
3495 int sizeofMatchJump, sizeofJumpTable;
3498 if (!tree || !caseVals)
3501 /* the criteria for creating a jump table is */
3502 /* all integer numbers between the maximum & minimum must */
3503 /* be present , the maximum value should not exceed 255 */
3504 /* If not all integer numbers are present the algorithm */
3505 /* inserts jumps to the default label for the missing numbers */
3506 /* and decides later whether it is worth it */
3507 min = (int) floatFromVal (vch = caseVals);
3514 max = (int) floatFromVal (vch);
3516 /* Exit if the range is too large to handle with a jump table. */
3517 if (1 + max - min > port->jumptableCost.maxCount)
3520 switch (getSize (operandType (cond)))
3522 case 1: sizeIndex = 0; break;
3523 case 2: sizeIndex = 1; break;
3524 case 4: sizeIndex = 2; break;
3528 /* Compute the size cost of the range check and subtraction. */
3533 if (!(min==0 && IS_UNSIGNED (cetype)))
3534 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3535 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3538 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3540 /* If the size cost of handling a non-zero minimum exceeds the */
3541 /* cost of extending the range down to zero, then it might be */
3542 /* better to extend the range to zero. */
3543 if (min > 0 && sizeofMinCost >= (min * port->jumptableCost.sizeofElement))
3545 /* Only extend the jump table if it would still be manageable. */
3546 if (1 + max <= port->jumptableCost.maxCount)
3550 /* Compute the total size cost of a jump table. */
3551 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3552 + port->jumptableCost.sizeofDispatch
3553 + sizeofMinCost + sizeofMaxCost;
3555 /* Compute the total size cost of a match & jump sequence */
3556 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3558 /* If the size cost of the jump table is uneconomical then exit */
3559 if (sizeofMatchJump < sizeofJumpTable)
3562 /* The jump table is preferable. */
3564 /* First, a label for the default or missing cases. */
3565 if (tree->values.switchVals.swDefault)
3567 SNPRINTF (buffer, sizeof(buffer),
3569 tree->values.switchVals.swNum);
3573 SNPRINTF (buffer, sizeof(buffer),
3575 tree->values.switchVals.swNum);
3577 falseLabel = newiTempLabel (buffer);
3579 /* Build the list of labels for the jump table. */
3581 t = (int) floatFromVal (vch);
3582 for (i=min; i<=max; i++)
3586 /* Explicit case: make a new label for it. */
3587 SNPRINTF (buffer, sizeof(buffer),
3589 tree->values.switchVals.swNum,
3591 addSet (&labels, newiTempLabel (buffer));
3594 t = (int) floatFromVal (vch);
3598 /* Implicit case: use the default label. */
3599 addSet (&labels, falseLabel);
3603 /* If cond is volatile, it might change after the boundary */
3604 /* conditions are tested to an out of bounds value, causing */
3605 /* a jump to a location outside of the jump table. To avoid */
3606 /* this possibility, use a non-volatile copy of it instead. */
3607 if (IS_OP_VOLATILE (cond))
3612 newcond = newiTempOperand (operandType (cond), TRUE);
3613 newcond->isvolatile = 0;
3614 ic = newiCode ('=', NULL, cond);
3615 IC_RESULT (ic) = newcond;
3620 /* first we rule out the boundary conditions */
3621 /* if only optimization says so */
3624 sym_link *cetype = getSpec (operandType (cond));
3625 /* no need to check the lower bound if
3626 the condition is unsigned & minimum value is zero */
3627 if (!(min == 0 && IS_UNSIGNED (cetype)))
3629 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3630 ic = newiCodeCondition (boundary, falseLabel, NULL);
3634 /* now for upper bounds */
3635 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3636 ic = newiCodeCondition (boundary, falseLabel, NULL);
3640 /* if the min is not zero then we no make it zero */
3643 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3644 if (!IS_LITERAL(getSpec(operandType(cond))))
3645 setOperandType (cond, UCHARTYPE);
3648 /* now create the jumptable */
3649 ic = newiCode (JUMPTABLE, NULL, NULL);
3650 IC_JTCOND (ic) = cond;
3651 IC_JTLABELS (ic) = labels;
3656 /*-----------------------------------------------------------------*/
3657 /* geniCodeSwitch - changes a switch to a if statement */
3658 /*-----------------------------------------------------------------*/
3660 geniCodeSwitch (ast * tree,int lvl)
3663 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3664 value *caseVals = tree->values.switchVals.swVals;
3665 symbol *trueLabel, *falseLabel;
3667 /* If the condition is a literal, then just jump to the */
3668 /* appropriate case label. */
3669 if (IS_LITERAL(getSpec(operandType(cond))))
3671 int switchVal, caseVal;
3673 switchVal = (int) floatFromVal (cond->operand.valOperand);
3676 caseVal = (int) floatFromVal (caseVals);
3677 if (caseVal == switchVal)
3679 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3680 tree->values.switchVals.swNum, caseVal);
3681 trueLabel = newiTempLabel (buffer);
3682 geniCodeGoto (trueLabel);
3685 caseVals = caseVals->next;
3687 goto defaultOrBreak;
3690 /* if we can make this a jump table */
3691 if (geniCodeJumpTable (cond, caseVals, tree))
3692 goto jumpTable; /* no need for the comparison */
3694 /* for the cases defined do */
3698 operand *compare = geniCodeLogic (cond,
3699 operandFromValue (caseVals),
3702 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3703 tree->values.switchVals.swNum,
3704 (int) floatFromVal (caseVals));
3705 trueLabel = newiTempLabel (buffer);
3707 ic = newiCodeCondition (compare, trueLabel, NULL);
3709 caseVals = caseVals->next;
3714 /* if default is present then goto break else break */
3715 if (tree->values.switchVals.swDefault)
3717 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3721 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3724 falseLabel = newiTempLabel (buffer);
3725 geniCodeGoto (falseLabel);
3728 ast2iCode (tree->right,lvl+1);
3731 /*-----------------------------------------------------------------*/
3732 /* geniCodeInline - intermediate code for inline assembler */
3733 /*-----------------------------------------------------------------*/
3735 geniCodeInline (ast * tree)
3739 ic = newiCode (INLINEASM, NULL, NULL);
3740 IC_INLINE (ic) = tree->values.inlineasm;
3744 /*-----------------------------------------------------------------*/
3745 /* geniCodeArrayInit - intermediate code for array initializer */
3746 /*-----------------------------------------------------------------*/
3748 geniCodeArrayInit (ast * tree, operand *array)
3752 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3753 ic = newiCode (ARRAYINIT, array, NULL);
3754 IC_ARRAYILIST (ic) = tree->values.constlist;
3756 operand *left=newOperand(), *right=newOperand();
3757 left->type=right->type=SYMBOL;
3758 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3759 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3760 ic = newiCode (ARRAYINIT, left, right);
3765 /*-----------------------------------------------------------------*/
3766 /* geniCodeCritical - intermediate code for a critical statement */
3767 /*-----------------------------------------------------------------*/
3769 geniCodeCritical (ast *tree, int lvl)
3774 /* If op is NULL, the original interrupt state will saved on */
3775 /* the stack. Otherwise, it will be saved in op. */
3777 /* Generate a save of the current interrupt state & disabled */
3778 ic = newiCode (CRITICAL, NULL, NULL);
3779 IC_RESULT (ic) = op;
3782 /* Generate the critical code sequence */
3783 if (tree->left && tree->left->type == EX_VALUE)
3784 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3786 ast2iCode (tree->left,lvl+1);
3788 /* Generate a restore of the original interrupt state */
3789 ic = newiCode (ENDCRITICAL, NULL, op);
3793 /*-----------------------------------------------------------------*/
3794 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3795 /* particular case. Ie : assigning or dereferencing array or ptr */
3796 /*-----------------------------------------------------------------*/
3797 set * lvaluereqSet = NULL;
3798 typedef struct lvalItem
3805 /*-----------------------------------------------------------------*/
3806 /* addLvaluereq - add a flag for lvalreq for current ast level */
3807 /*-----------------------------------------------------------------*/
3808 void addLvaluereq(int lvl)
3810 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3813 addSetHead(&lvaluereqSet,lpItem);
3816 /*-----------------------------------------------------------------*/
3817 /* delLvaluereq - del a flag for lvalreq for current ast level */
3818 /*-----------------------------------------------------------------*/
3822 lpItem = getSet(&lvaluereqSet);
3823 if(lpItem) Safe_free(lpItem);
3825 /*-----------------------------------------------------------------*/
3826 /* clearLvaluereq - clear lvalreq flag */
3827 /*-----------------------------------------------------------------*/
3828 void clearLvaluereq()
3831 lpItem = peekSet(lvaluereqSet);
3832 if(lpItem) lpItem->req = 0;
3834 /*-----------------------------------------------------------------*/
3835 /* getLvaluereq - get the last lvalreq level */
3836 /*-----------------------------------------------------------------*/
3837 int getLvaluereqLvl()
3840 lpItem = peekSet(lvaluereqSet);
3841 if(lpItem) return lpItem->lvl;
3844 /*-----------------------------------------------------------------*/
3845 /* isLvaluereq - is lvalreq valid for this level ? */
3846 /*-----------------------------------------------------------------*/
3847 int isLvaluereq(int lvl)
3850 lpItem = peekSet(lvaluereqSet);
3851 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3855 /*-----------------------------------------------------------------*/
3856 /* ast2iCode - creates an icodeList from an ast */
3857 /*-----------------------------------------------------------------*/
3859 ast2iCode (ast * tree,int lvl)
3861 operand *left = NULL;
3862 operand *right = NULL;
3866 /* set the global variables for filename & line number */
3868 filename = tree->filename;
3870 lineno = tree->lineno;
3872 block = tree->block;
3874 scopeLevel = tree->level;
3876 seqPoint = tree->seqPoint;
3878 if (tree->type == EX_VALUE)
3879 return operandFromValue (tree->opval.val);
3881 if (tree->type == EX_LINK)
3882 return operandFromLink (tree->opval.lnk);
3884 /* if we find a nullop */
3885 if (tree->type == EX_OP &&
3886 (tree->opval.op == NULLOP ||
3887 tree->opval.op == BLOCK))
3889 if (tree->left && tree->left->type == EX_VALUE)
3890 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3892 ast2iCode (tree->left,lvl+1);
3893 if (tree->right && tree->right->type == EX_VALUE)
3894 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3896 ast2iCode (tree->right,lvl+1);
3900 /* special cases for not evaluating */
3901 if (tree->opval.op != ':' &&
3902 tree->opval.op != '?' &&
3903 tree->opval.op != CALL &&
3904 tree->opval.op != IFX &&
3905 tree->opval.op != AND_OP &&
3906 tree->opval.op != OR_OP &&
3907 tree->opval.op != LABEL &&
3908 tree->opval.op != GOTO &&
3909 tree->opval.op != SWITCH &&
3910 tree->opval.op != FUNCTION &&
3911 tree->opval.op != INLINEASM &&
3912 tree->opval.op != CRITICAL)
3915 if (IS_ASSIGN_OP (tree->opval.op) ||
3916 IS_DEREF_OP (tree) ||
3917 (tree->opval.op == '&' && !tree->right) ||
3918 tree->opval.op == PTR_OP)
3921 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3922 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3925 left = operandFromAst (tree->left,lvl);
3927 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3928 left = geniCodeRValue (left, TRUE);
3932 left = operandFromAst (tree->left,lvl);
3934 if (tree->opval.op == INC_OP ||
3935 tree->opval.op == DEC_OP)
3938 right = operandFromAst (tree->right,lvl);
3943 right = operandFromAst (tree->right,lvl);
3947 /* now depending on the type of operand */
3948 /* this will be a biggy */
3949 switch (tree->opval.op)
3952 case '[': /* array operation */
3954 //sym_link *ltype = operandType (left);
3955 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3956 left = geniCodeRValue (left, FALSE);
3957 right = geniCodeRValue (right, TRUE);
3960 return geniCodeArray (left, right,lvl);
3962 case '.': /* structure dereference */
3963 if (IS_PTR (operandType (left)))
3964 left = geniCodeRValue (left, TRUE);
3966 left = geniCodeRValue (left, FALSE);
3968 return geniCodeStruct (left, right, tree->lvalue);
3970 case PTR_OP: /* structure pointer dereference */
3973 pType = operandType (left);
3974 left = geniCodeRValue (left, TRUE);
3976 setOClass (pType, getSpec (operandType (left)));
3979 return geniCodeStruct (left, right, tree->lvalue);
3981 case INC_OP: /* increment operator */
3983 return geniCodePostInc (left);
3985 return geniCodePreInc (right, tree->lvalue);
3987 case DEC_OP: /* decrement operator */
3989 return geniCodePostDec (left);
3991 return geniCodePreDec (right, tree->lvalue);
3993 case '&': /* bitwise and or address of operator */
3995 { /* this is a bitwise operator */
3996 left = geniCodeRValue (left, FALSE);
3997 right = geniCodeRValue (right, FALSE);
3998 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4001 return geniCodeAddressOf (left);
4003 case '|': /* bitwise or & xor */
4005 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4006 geniCodeRValue (right, FALSE),
4011 return geniCodeDivision (geniCodeRValue (left, FALSE),
4012 geniCodeRValue (right, FALSE),
4013 getResultTypeFromType (tree->ftype));
4016 return geniCodeModulus (geniCodeRValue (left, FALSE),
4017 geniCodeRValue (right, FALSE),
4018 getResultTypeFromType (tree->ftype));
4021 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4022 geniCodeRValue (right, FALSE),
4023 getResultTypeFromType (tree->ftype));
4025 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4029 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4030 geniCodeRValue (right, FALSE),
4031 getResultTypeFromType (tree->ftype));
4033 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4037 return geniCodeAdd (geniCodeRValue (left, FALSE),
4038 geniCodeRValue (right, FALSE),
4039 getResultTypeFromType (tree->ftype),
4042 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4045 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4046 geniCodeRValue (right, FALSE),
4047 getResultTypeFromType (tree->ftype));
4050 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4051 geniCodeRValue (right, FALSE));
4053 #if 0 // this indeed needs a second thought
4057 // let's keep this simple: get the rvalue we need
4058 op=geniCodeRValue (right, FALSE);
4059 // now cast it to whatever we want
4060 op=geniCodeCast (operandType(left), op, FALSE);
4061 // if this is going to be used as an lvalue, make it so
4067 #else // bug #604575, is it a bug ????
4068 return geniCodeCast (operandType (left),
4069 geniCodeRValue (right, FALSE), FALSE);
4076 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4081 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4082 setOperandType (op, UCHARTYPE);
4087 return geniCodeLogicAndOr (tree, lvl);
4094 /* different compilers (even different gccs) evaluate
4095 the two calls in a different order. to get the same
4096 result on all machines we've to specify a clear sequence.
4097 return geniCodeLogic (geniCodeRValue (left, FALSE),
4098 geniCodeRValue (right, FALSE),
4102 operand *leftOp, *rightOp;
4104 leftOp = geniCodeRValue (left , FALSE);
4105 rightOp = geniCodeRValue (right, FALSE);
4107 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4110 return geniCodeConditional (tree,lvl);
4113 return operandFromLit (getSize (tree->right->ftype));
4117 sym_link *rtype = operandType (right);
4118 sym_link *ltype = operandType (left);
4119 if (IS_PTR (rtype) && IS_ITEMP (right)
4120 && right->isaddr && compareType (rtype->next, ltype) == 1)
4121 right = geniCodeRValue (right, TRUE);
4123 right = geniCodeRValue (right, FALSE);
4125 geniCodeAssign (left, right, 0, 1);
4130 geniCodeAssign (left,
4131 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4133 geniCodeRValue (right, FALSE),
4134 getResultTypeFromType (tree->ftype)),
4139 geniCodeAssign (left,
4140 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4142 geniCodeRValue (right, FALSE),
4143 getResultTypeFromType (tree->ftype)),
4147 geniCodeAssign (left,
4148 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4150 geniCodeRValue (right, FALSE),
4151 getResultTypeFromType (tree->ftype)),
4155 sym_link *rtype = operandType (right);
4156 sym_link *ltype = operandType (left);
4157 if (IS_PTR (rtype) && IS_ITEMP (right)
4158 && right->isaddr && compareType (rtype->next, ltype) == 1)
4159 right = geniCodeRValue (right, TRUE);
4161 right = geniCodeRValue (right, FALSE);
4164 return geniCodeAssign (left,
4165 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4168 getResultTypeFromType (tree->ftype),
4174 sym_link *rtype = operandType (right);
4175 sym_link *ltype = operandType (left);
4176 if (IS_PTR (rtype) && IS_ITEMP (right)
4177 && right->isaddr && compareType (rtype->next, ltype) == 1)
4179 right = geniCodeRValue (right, TRUE);
4183 right = geniCodeRValue (right, FALSE);
4186 geniCodeAssign (left,
4187 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4190 getResultTypeFromType (tree->ftype)),
4195 geniCodeAssign (left,
4196 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4198 geniCodeRValue (right, FALSE),
4199 getResultTypeFromType (tree->ftype)),
4203 geniCodeAssign (left,
4204 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4206 geniCodeRValue (right, FALSE)), 0, 1);
4209 geniCodeAssign (left,
4210 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4212 geniCodeRValue (right, FALSE),
4214 operandType (left)), 0, 1);
4217 geniCodeAssign (left,
4218 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4220 geniCodeRValue (right, FALSE),
4222 operandType (left)), 0, 1);
4225 geniCodeAssign (left,
4226 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4228 geniCodeRValue (right, FALSE),
4230 operandType (left)), 0, 1);
4232 return geniCodeRValue (right, FALSE);
4235 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4238 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4239 return ast2iCode (tree->right,lvl+1);
4242 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4243 return ast2iCode (tree->right,lvl+1);
4246 geniCodeFunctionBody (tree,lvl);
4250 geniCodeReturn (right);
4254 geniCodeIfx (tree,lvl);
4258 geniCodeSwitch (tree,lvl);
4262 geniCodeInline (tree);
4266 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4270 geniCodeCritical (tree, lvl);
4276 /*-----------------------------------------------------------------*/
4277 /* reverseICChain - gets from the list and creates a linkedlist */
4278 /*-----------------------------------------------------------------*/
4285 while ((loop = getSet (&iCodeChain)))
4297 /*-----------------------------------------------------------------*/
4298 /* iCodeFromAst - given an ast will convert it to iCode */
4299 /*-----------------------------------------------------------------*/
4301 iCodeFromAst (ast * tree)
4303 returnLabel = newiTempLabel ("_return");
4304 entryLabel = newiTempLabel ("_entry");
4306 return reverseiCChain ();
4309 static const char *opTypeToStr(OPTYPE op)
4313 case SYMBOL: return "symbol";
4314 case VALUE: return "value";
4315 case TYPE: return "type";
4317 return "undefined type";
4321 operand *validateOpType(operand *op,
4328 if (op && op->type == type)
4333 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4334 " expected %s, got %s\n",
4335 macro, args, file, line,
4336 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4338 return op; // never reached, makes compiler happy.