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 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_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 pointer to an 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 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2422 return IC_RESULT (ic);
2425 /*-----------------------------------------------------------------*/
2426 /* geniCodeStruct - generates intermediate code for structures */
2427 /*-----------------------------------------------------------------*/
2429 geniCodeStruct (operand * left, operand * right, bool islval)
2432 sym_link *type = operandType (left);
2433 sym_link *etype = getSpec (type);
2435 symbol *element = getStructElement (SPEC_STRUCT (etype),
2436 right->operand.symOperand);
2438 wassert(IS_SYMOP(right));
2440 /* add the offset */
2441 ic = newiCode ('+', left, operandFromLit (element->offset));
2443 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2445 /* preserve the storage & output class of the struct */
2446 /* as well as the volatile attribute */
2447 retype = getSpec (operandType (IC_RESULT (ic)));
2448 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2449 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2450 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2451 SPEC_CONST (retype) |= SPEC_CONST (etype);
2453 if (IS_PTR (element->type))
2454 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2456 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2459 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2462 /*-----------------------------------------------------------------*/
2463 /* geniCodePostInc - generate int code for Post increment */
2464 /*-----------------------------------------------------------------*/
2466 geniCodePostInc (operand * op)
2470 sym_link *optype = operandType (op);
2472 operand *rv = (IS_ITEMP (op) ?
2473 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2475 sym_link *rvtype = operandType (rv);
2478 /* if this is not an address we have trouble */
2481 werror (E_LVALUE_REQUIRED, "++");
2485 rOp = newiTempOperand (rvtype, 0);
2486 OP_SYMBOL(rOp)->noSpilLoc = 1;
2489 OP_SYMBOL(rv)->noSpilLoc = 1;
2491 geniCodeAssign (rOp, rv, 0, 0);
2493 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2494 if (IS_FLOAT (rvtype))
2495 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2497 ic = newiCode ('+', rv, operandFromLit (size));
2499 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2502 geniCodeAssign (op, result, 0, 0);
2508 /*-----------------------------------------------------------------*/
2509 /* geniCodePreInc - generate code for preIncrement */
2510 /*-----------------------------------------------------------------*/
2512 geniCodePreInc (operand * op, bool lvalue)
2515 sym_link *optype = operandType (op);
2516 operand *rop = (IS_ITEMP (op) ?
2517 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2519 sym_link *roptype = operandType (rop);
2525 werror (E_LVALUE_REQUIRED, "++");
2530 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2531 if (IS_FLOAT (roptype))
2532 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2534 ic = newiCode ('+', rop, operandFromLit (size));
2535 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2538 (void) geniCodeAssign (op, result, 0, 0);
2539 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2545 /*-----------------------------------------------------------------*/
2546 /* geniCodePostDec - generates code for Post decrement */
2547 /*-----------------------------------------------------------------*/
2549 geniCodePostDec (operand * op)
2553 sym_link *optype = operandType (op);
2555 operand *rv = (IS_ITEMP (op) ?
2556 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2558 sym_link *rvtype = operandType (rv);
2561 /* if this is not an address we have trouble */
2564 werror (E_LVALUE_REQUIRED, "--");
2568 rOp = newiTempOperand (rvtype, 0);
2569 OP_SYMBOL(rOp)->noSpilLoc = 1;
2572 OP_SYMBOL(rv)->noSpilLoc = 1;
2574 geniCodeAssign (rOp, rv, 0, 0);
2576 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2577 if (IS_FLOAT (rvtype))
2578 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2580 ic = newiCode ('-', rv, operandFromLit (size));
2582 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2585 geniCodeAssign (op, result, 0, 0);
2591 /*-----------------------------------------------------------------*/
2592 /* geniCodePreDec - generate code for pre decrement */
2593 /*-----------------------------------------------------------------*/
2595 geniCodePreDec (operand * op, bool lvalue)
2598 sym_link *optype = operandType (op);
2599 operand *rop = (IS_ITEMP (op) ?
2600 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2602 sym_link *roptype = operandType (rop);
2608 werror (E_LVALUE_REQUIRED, "--");
2613 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2614 if (IS_FLOAT (roptype))
2615 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2617 ic = newiCode ('-', rop, operandFromLit (size));
2618 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2621 (void) geniCodeAssign (op, result, 0, 0);
2622 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2629 /*-----------------------------------------------------------------*/
2630 /* geniCodeBitwise - gen int code for bitWise operators */
2631 /*-----------------------------------------------------------------*/
2633 geniCodeBitwise (operand * left, operand * right,
2634 int oper, sym_link * resType)
2638 left = geniCodeCast (resType, left, TRUE);
2639 right = geniCodeCast (resType, right, TRUE);
2641 ic = newiCode (oper, left, right);
2642 IC_RESULT (ic) = newiTempOperand (resType, 0);
2645 return IC_RESULT (ic);
2648 /*-----------------------------------------------------------------*/
2649 /* geniCodeAddressOf - gens icode for '&' address of operator */
2650 /*-----------------------------------------------------------------*/
2652 geniCodeAddressOf (operand * op)
2656 sym_link *optype = operandType (op);
2657 sym_link *opetype = getSpec (optype);
2659 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2661 op = operandFromOperand (op);
2666 /* lvalue check already done in decorateType */
2667 /* this must be a lvalue */
2668 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2669 /* werror (E_LVALUE_REQUIRED,"&"); */
2673 p = newLink (DECLARATOR);
2675 /* set the pointer depending on the storage class */
2676 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2678 p->next = copyLinkChain (optype);
2680 /* if already a temp */
2683 setOperandType (op, p);
2688 /* other wise make this of the type coming in */
2689 ic = newiCode (ADDRESS_OF, op, NULL);
2690 IC_RESULT (ic) = newiTempOperand (p, 1);
2691 IC_RESULT (ic)->isaddr = 0;
2693 return IC_RESULT (ic);
2695 /*-----------------------------------------------------------------*/
2696 /* setOClass - sets the output class depending on the pointer type */
2697 /*-----------------------------------------------------------------*/
2699 setOClass (sym_link * ptr, sym_link * spec)
2701 switch (DCL_TYPE (ptr))
2704 SPEC_OCLS (spec) = data;
2708 SPEC_OCLS (spec) = generic;
2712 SPEC_OCLS (spec) = xdata;
2716 SPEC_OCLS (spec) = code;
2720 SPEC_OCLS (spec) = idata;
2724 SPEC_OCLS (spec) = xstack;
2728 SPEC_OCLS (spec) = eeprom;
2737 /*-----------------------------------------------------------------*/
2738 /* geniCodeDerefPtr - dereference pointer with '*' */
2739 /*-----------------------------------------------------------------*/
2741 geniCodeDerefPtr (operand * op,int lvl)
2743 sym_link *rtype, *retype;
2744 sym_link *optype = operandType (op);
2746 // if this is an array then array access
2747 if (IS_ARRAY (optype)) {
2748 // don't worry, this will be optimized out later
2749 return geniCodeArray (op, operandFromLit (0), lvl);
2752 // just in case someone screws up
2753 wassert (IS_PTR (optype));
2755 if (IS_TRUE_SYMOP (op))
2758 op = geniCodeRValue (op, TRUE);
2761 /* now get rid of the pointer part */
2762 if (isLvaluereq(lvl) && IS_ITEMP (op))
2764 retype = getSpec (rtype = copyLinkChain (optype));
2768 retype = getSpec (rtype = copyLinkChain (optype->next));
2769 /* outputclass needs 2b updated */
2770 setOClass (optype, retype);
2773 op->isGptr = IS_GENPTR (optype);
2775 op->isaddr = (IS_PTR (rtype) ||
2776 IS_STRUCT (rtype) ||
2781 if (!isLvaluereq(lvl))
2782 op = geniCodeRValue (op, TRUE);
2784 setOperandType (op, rtype);
2789 /*-----------------------------------------------------------------*/
2790 /* geniCodeUnaryMinus - does a unary minus of the operand */
2791 /*-----------------------------------------------------------------*/
2793 geniCodeUnaryMinus (operand * op)
2796 sym_link *optype = operandType (op);
2798 if (IS_LITERAL (optype))
2799 return operandFromLit (-floatFromVal (op->operand.valOperand));
2801 ic = newiCode (UNARYMINUS, op, NULL);
2802 IC_RESULT (ic) = newiTempOperand (optype, 0);
2804 return IC_RESULT (ic);
2807 /*-----------------------------------------------------------------*/
2808 /* geniCodeLeftShift - gen i code for left shift */
2809 /*-----------------------------------------------------------------*/
2811 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2816 ic = newiCode (LEFT_OP, left, right);
2818 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2819 IC_RESULT (ic) = newiTempOperand (resType, 0);
2821 return IC_RESULT (ic);
2824 /*-----------------------------------------------------------------*/
2825 /* geniCodeRightShift - gen i code for right shift */
2826 /*-----------------------------------------------------------------*/
2828 geniCodeRightShift (operand * left, operand * right)
2832 ic = newiCode (RIGHT_OP, left, right);
2833 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2835 return IC_RESULT (ic);
2838 /*-----------------------------------------------------------------*/
2839 /* geniCodeLogic- logic code */
2840 /*-----------------------------------------------------------------*/
2842 geniCodeLogic (operand * left, operand * right, int op)
2846 sym_link *rtype = operandType (right);
2847 sym_link *ltype = operandType (left);
2849 /* left is integral type and right is literal then
2850 check if the literal value is within bounds */
2851 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2853 checkConstantRange(ltype,
2854 OP_VALUE(right), "compare operation", 1);
2857 /* if one operand is a pointer and the other is a literal generic void pointer,
2858 change the type of the literal generic void pointer to match the other pointer */
2859 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2860 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2862 /* find left's definition */
2863 ic = (iCode *) setFirstItem (iCodeChain);
2866 if (((ic->op == CAST) || (ic->op == '='))
2867 && isOperandEqual(left, IC_RESULT (ic)))
2870 ic = setNextItem (iCodeChain);
2872 /* if casting literal to generic pointer, then cast to rtype instead */
2873 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2875 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2876 ltype = operandType(left);
2879 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2880 && IS_PTR (ltype) && !IS_GENPTR(ltype))
2882 /* find right's definition */
2883 ic = (iCode *) setFirstItem (iCodeChain);
2886 if (((ic->op == CAST) || (ic->op == '='))
2887 && isOperandEqual(right, IC_RESULT (ic)))
2890 ic = setNextItem (iCodeChain);
2892 /* if casting literal to generic pointer, then cast to rtype instead */
2893 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2895 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2896 rtype = operandType(right);
2900 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
2902 ic = newiCode (op, left, right);
2903 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2905 /* if comparing float
2906 and not a '==' || '!=' || '&&' || '||' (these
2908 if (IS_FLOAT(ctype) &&
2916 return IC_RESULT (ic);
2919 /*-----------------------------------------------------------------*/
2920 /* geniCodeLogicAndOr - && || operations */
2921 /*-----------------------------------------------------------------*/
2923 geniCodeLogicAndOr (ast *tree, int lvl)
2926 symbol *falseLabel = newiTempLabel (NULL);
2927 symbol *trueLabel = newiTempLabel (NULL);
2928 symbol *exitLabel = newiTempLabel (NULL);
2929 operand *op, *result, *condition;
2931 /* AND_OP and OR_OP are no longer generated because of bug-905492.
2932 They can be reenabled by executing the following block. If you find
2933 a decent optimization you could start right here:
2938 operand *leftOp, *rightOp;
2940 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
2941 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
2943 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
2947 /* generate two IFX for the '&&' or '||' op */
2949 /* evaluate left operand */
2950 condition = ast2iCode (tree->left, lvl + 1);
2951 op = geniCodeRValue (condition, FALSE);
2953 /* test left operand */
2954 if (tree->opval.op == AND_OP)
2955 ic = newiCodeCondition (op, NULL, falseLabel);
2957 ic = newiCodeCondition (op, trueLabel, NULL);
2960 /* evaluate right operand */
2961 condition = ast2iCode (tree->right, lvl + 1);
2962 op = geniCodeRValue (condition, FALSE);
2964 /* test right operand */
2965 ic = newiCodeCondition (op, trueLabel, NULL);
2968 /* store 0 or 1 in result */
2969 result = newiTempOperand (newCharLink(), 1);
2971 geniCodeLabel (falseLabel);
2972 geniCodeAssign (result, operandFromLit (0), 0, 0);
2973 /* generate an unconditional goto */
2974 geniCodeGoto (exitLabel);
2976 geniCodeLabel (trueLabel);
2977 geniCodeAssign (result, operandFromLit (1), 0, 0);
2979 geniCodeLabel (exitLabel);
2984 /*-----------------------------------------------------------------*/
2985 /* geniCodeUnary - for a a generic unary operation */
2986 /*-----------------------------------------------------------------*/
2988 geniCodeUnary (operand * op, int oper)
2990 iCode *ic = newiCode (oper, op, NULL);
2992 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2994 return IC_RESULT (ic);
2997 /*-----------------------------------------------------------------*/
2998 /* geniCodeConditional - geniCode for '?' ':' operation */
2999 /*-----------------------------------------------------------------*/
3001 geniCodeConditional (ast * tree,int lvl)
3004 symbol *falseLabel = newiTempLabel (NULL);
3005 symbol *exitLabel = newiTempLabel (NULL);
3006 operand *cond = ast2iCode (tree->left,lvl+1);
3007 operand *true, *false, *result;
3009 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3013 true = ast2iCode (tree->right->left,lvl+1);
3015 /* move the value to a new Operand */
3016 result = newiTempOperand (tree->right->ftype, 0);
3017 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3019 /* generate an unconditional goto */
3020 geniCodeGoto (exitLabel);
3022 /* now for the right side */
3023 geniCodeLabel (falseLabel);
3025 false = ast2iCode (tree->right->right,lvl+1);
3026 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3028 /* create the exit label */
3029 geniCodeLabel (exitLabel);
3034 /*-----------------------------------------------------------------*/
3035 /* geniCodeAssign - generate code for assignment */
3036 /*-----------------------------------------------------------------*/
3038 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3041 sym_link *ltype = operandType (left);
3042 sym_link *rtype = operandType (right);
3044 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3046 werror (E_LVALUE_REQUIRED, "assignment");
3050 /* left is integral type and right is literal then
3051 check if the literal value is within bounds */
3052 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3054 checkConstantRange(ltype,
3055 OP_VALUE(right), "= operation", 0);
3058 /* if the left & right type don't exactly match */
3059 /* if pointer set then make sure the check is
3060 done with the type & not the pointer */
3061 /* then cast rights type to left */
3063 /* first check the type for pointer assignement */
3064 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3065 compareType (ltype, rtype) <= 0)
3067 if (compareType (ltype->next, rtype) < 0)
3068 right = geniCodeCast (ltype->next, right, TRUE);
3070 else if (compareType (ltype, rtype) < 0)
3071 right = geniCodeCast (ltype, right, TRUE);
3073 /* If left is a true symbol & ! volatile
3074 create an assignment to temporary for
3075 the right & then assign this temporary
3076 to the symbol. This is SSA (static single
3077 assignment). Isn't it simple and folks have
3078 published mountains of paper on it */
3079 if (IS_TRUE_SYMOP (left) &&
3080 !isOperandVolatile (left, FALSE) &&
3081 isOperandGlobal (left))
3085 if (IS_TRUE_SYMOP (right))
3086 sym = OP_SYMBOL (right);
3087 ic = newiCode ('=', NULL, right);
3088 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3089 SPIL_LOC (right) = sym;
3093 ic = newiCode ('=', NULL, right);
3094 IC_RESULT (ic) = left;
3097 /* if left isgptr flag is set then support
3098 routine will be required */
3102 ic->nosupdate = nosupdate;
3106 /*-----------------------------------------------------------------*/
3107 /* geniCodeDummyRead - generate code for dummy read */
3108 /*-----------------------------------------------------------------*/
3110 geniCodeDummyRead (operand * op)
3113 sym_link *type = operandType (op);
3115 if (!IS_VOLATILE(type))
3118 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3124 /*-----------------------------------------------------------------*/
3125 /* geniCodeSEParms - generate code for side effecting fcalls */
3126 /*-----------------------------------------------------------------*/
3128 geniCodeSEParms (ast * parms,int lvl)
3133 if (parms->type == EX_OP && parms->opval.op == PARAM)
3135 geniCodeSEParms (parms->left,lvl);
3136 geniCodeSEParms (parms->right,lvl);
3140 /* hack don't like this but too lazy to think of
3142 if (IS_ADDRESS_OF_OP (parms))
3143 parms->left->lvalue = 1;
3145 if (IS_CAST_OP (parms) &&
3146 IS_PTR (parms->ftype) &&
3147 IS_ADDRESS_OF_OP (parms->right))
3148 parms->right->left->lvalue = 1;
3150 parms->opval.oprnd =
3151 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3153 parms->type = EX_OPERAND;
3154 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3155 SPEC_ARGREG(parms->ftype);
3158 /*-----------------------------------------------------------------*/
3159 /* geniCodeParms - generates parameters */
3160 /*-----------------------------------------------------------------*/
3162 geniCodeParms (ast * parms, value *argVals, int *stack,
3163 sym_link * ftype, int lvl)
3171 if (argVals==NULL) {
3173 argVals = FUNC_ARGS (ftype);
3176 /* if this is a param node then do the left & right */
3177 if (parms->type == EX_OP && parms->opval.op == PARAM)
3179 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3180 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3184 /* get the parameter value */
3185 if (parms->type == EX_OPERAND)
3186 pval = parms->opval.oprnd;
3189 /* maybe this else should go away ?? */
3190 /* hack don't like this but too lazy to think of
3192 if (IS_ADDRESS_OF_OP (parms))
3193 parms->left->lvalue = 1;
3195 if (IS_CAST_OP (parms) &&
3196 IS_PTR (parms->ftype) &&
3197 IS_ADDRESS_OF_OP (parms->right))
3198 parms->right->left->lvalue = 1;
3200 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3203 /* if register parm then make it a send */
3204 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3205 IFFUNC_ISBUILTIN(ftype))
3207 ic = newiCode (SEND, pval, NULL);
3208 ic->argreg = SPEC_ARGREG(parms->etype);
3209 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3214 /* now decide whether to push or assign */
3215 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3219 operand *top = operandFromSymbol (argVals->sym);
3220 /* clear useDef and other bitVectors */
3221 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3222 geniCodeAssign (top, pval, 1, 0);
3226 sym_link *p = operandType (pval);
3228 ic = newiCode (IPUSH, pval, NULL);
3230 /* update the stack adjustment */
3231 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3236 argVals=argVals->next;
3240 /*-----------------------------------------------------------------*/
3241 /* geniCodeCall - generates temp code for calling */
3242 /*-----------------------------------------------------------------*/
3244 geniCodeCall (operand * left, ast * parms,int lvl)
3248 sym_link *type, *etype;
3252 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3253 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3254 werror (E_FUNCTION_EXPECTED);
3255 return operandFromValue(valueFromLit(0));
3258 /* take care of parameters with side-effecting
3259 function calls in them, this is required to take care
3260 of overlaying function parameters */
3261 geniCodeSEParms (parms,lvl);
3263 ftype = operandType (left);
3264 if (IS_CODEPTR (ftype))
3265 ftype = ftype->next;
3267 /* first the parameters */
3268 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3270 /* now call : if symbol then pcall */
3271 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3272 ic = newiCode (PCALL, left, NULL);
3274 ic = newiCode (CALL, left, NULL);
3277 type = copyLinkChain (ftype->next);
3278 etype = getSpec (type);
3279 SPEC_EXTR (etype) = 0;
3280 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3284 /* stack adjustment after call */
3285 ic->parmBytes = stack;
3290 /*-----------------------------------------------------------------*/
3291 /* geniCodeReceive - generate intermediate code for "receive" */
3292 /*-----------------------------------------------------------------*/
3294 geniCodeReceive (value * args)
3296 /* for all arguments that are passed in registers */
3300 if (IS_REGPARM (args->etype))
3302 operand *opr = operandFromValue (args);
3304 symbol *sym = OP_SYMBOL (opr);
3307 /* we will use it after all optimizations
3308 and before liveRange calculation */
3309 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3312 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3313 options.stackAuto == 0 &&
3314 (!(options.model == MODEL_FLAT24)) )
3319 opl = newiTempOperand (args->type, 0);
3321 sym->reqv->key = sym->key;
3322 OP_SYMBOL (sym->reqv)->key = sym->key;
3323 OP_SYMBOL (sym->reqv)->isreqv = 1;
3324 OP_SYMBOL (sym->reqv)->islocal = 0;
3325 SPIL_LOC (sym->reqv) = sym;
3329 ic = newiCode (RECEIVE, NULL, NULL);
3330 ic->argreg = SPEC_ARGREG(args->etype);
3332 currFunc->recvSize = getSize (sym->type);
3335 IC_RESULT (ic) = opr;
3343 /*-----------------------------------------------------------------*/
3344 /* geniCodeFunctionBody - create the function body */
3345 /*-----------------------------------------------------------------*/
3347 geniCodeFunctionBody (ast * tree,int lvl)
3354 /* reset the auto generation */
3360 func = ast2iCode (tree->left,lvl+1);
3361 fetype = getSpec (operandType (func));
3363 savelineno = lineno;
3364 lineno = OP_SYMBOL (func)->lineDef;
3365 /* create an entry label */
3366 geniCodeLabel (entryLabel);
3367 lineno = savelineno;
3369 /* create a proc icode */
3370 ic = newiCode (FUNCTION, func, NULL);
3371 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3376 /* for all parameters that are passed
3377 on registers add a "receive" */
3378 geniCodeReceive (tree->values.args);
3380 /* generate code for the body */
3381 ast2iCode (tree->right,lvl+1);
3383 /* create a label for return */
3384 geniCodeLabel (returnLabel);
3386 /* now generate the end proc */
3387 ic = newiCode (ENDFUNCTION, func, NULL);
3393 /*-----------------------------------------------------------------*/
3394 /* geniCodeReturn - gen icode for 'return' statement */
3395 /*-----------------------------------------------------------------*/
3397 geniCodeReturn (operand * op)
3401 /* if the operand is present force an rvalue */
3403 op = geniCodeRValue (op, FALSE);
3405 ic = newiCode (RETURN, op, NULL);
3409 /*-----------------------------------------------------------------*/
3410 /* geniCodeIfx - generates code for extended if statement */
3411 /*-----------------------------------------------------------------*/
3413 geniCodeIfx (ast * tree,int lvl)
3416 operand *condition = ast2iCode (tree->left,lvl+1);
3419 /* if condition is null then exit */
3423 condition = geniCodeRValue (condition, FALSE);
3425 cetype = getSpec (operandType (condition));
3426 /* if the condition is a literal */
3427 if (IS_LITERAL (cetype))
3429 if (floatFromVal (condition->operand.valOperand))
3431 if (tree->trueLabel)
3432 geniCodeGoto (tree->trueLabel);
3438 if (tree->falseLabel)
3439 geniCodeGoto (tree->falseLabel);
3446 if (tree->trueLabel)
3448 ic = newiCodeCondition (condition,
3453 if (tree->falseLabel)
3454 geniCodeGoto (tree->falseLabel);
3458 ic = newiCodeCondition (condition,
3465 ast2iCode (tree->right,lvl+1);
3468 /*-----------------------------------------------------------------*/
3469 /* geniCodeJumpTable - tries to create a jump table for switch */
3470 /*-----------------------------------------------------------------*/
3472 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3474 int min, max, cnt = 1;
3481 int needRangeCheck = !optimize.noJTabBoundary
3482 || tree->values.switchVals.swDefault;
3483 sym_link *cetype = getSpec (operandType (cond));
3484 int sizeofMinCost, sizeofMaxCost;
3485 int sizeofMatchJump, sizeofJumpTable;
3488 if (!tree || !caseVals)
3491 /* the criteria for creating a jump table is */
3492 /* all integer numbers between the maximum & minimum must */
3493 /* be present , the maximum value should not exceed 255 */
3494 /* If not all integer numbers are present the algorithm */
3495 /* inserts jumps to the default label for the missing numbers */
3496 /* and decides later whether it is worth it */
3497 min = (int) floatFromVal (vch = caseVals);
3504 max = (int) floatFromVal (vch);
3506 /* Exit if the range is too large to handle with a jump table. */
3507 if (1 + max - min > port->jumptableCost.maxCount)
3510 switch (getSize (operandType (cond)))
3512 case 1: sizeIndex = 0; break;
3513 case 2: sizeIndex = 1; break;
3514 case 4: sizeIndex = 2; break;
3518 /* Compute the size cost of the range check and subtraction. */
3523 if (!(min==0 && IS_UNSIGNED (cetype)))
3524 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3525 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3528 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3530 /* If the size cost of handling a non-zero minimum exceeds the */
3531 /* cost of extending the range down to zero, then it might be */
3532 /* better to extend the range to zero. */
3533 if (min > 0 && sizeofMinCost >= (min * port->jumptableCost.sizeofElement))
3535 /* Only extend the jump table if it would still be manageable. */
3536 if (1 + max <= port->jumptableCost.maxCount)
3540 /* Compute the total size cost of a jump table. */
3541 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3542 + port->jumptableCost.sizeofDispatch
3543 + sizeofMinCost + sizeofMaxCost;
3545 /* Compute the total size cost of a match & jump sequence */
3546 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3548 /* If the size cost of the jump table is uneconomical then exit */
3549 if (sizeofMatchJump < sizeofJumpTable)
3552 /* The jump table is preferable. */
3554 /* First, a label for the default or missing cases. */
3555 if (tree->values.switchVals.swDefault)
3557 SNPRINTF (buffer, sizeof(buffer),
3559 tree->values.switchVals.swNum);
3563 SNPRINTF (buffer, sizeof(buffer),
3565 tree->values.switchVals.swNum);
3567 falseLabel = newiTempLabel (buffer);
3569 /* Build the list of labels for the jump table. */
3571 t = (int) floatFromVal (vch);
3572 for (i=min; i<=max; i++)
3576 /* Explicit case: make a new label for it. */
3577 SNPRINTF (buffer, sizeof(buffer),
3579 tree->values.switchVals.swNum,
3581 addSet (&labels, newiTempLabel (buffer));
3584 t = (int) floatFromVal (vch);
3588 /* Implicit case: use the default label. */
3589 addSet (&labels, falseLabel);
3593 /* If cond is volatile, it might change after the boundary */
3594 /* conditions are tested to an out of bounds value, causing */
3595 /* a jump to a location outside of the jump table. To avoid */
3596 /* this possibility, use a non-volatile copy of it instead. */
3597 if (IS_OP_VOLATILE (cond))
3602 newcond = newiTempOperand (operandType (cond), TRUE);
3603 newcond->isvolatile = 0;
3604 ic = newiCode ('=', NULL, cond);
3605 IC_RESULT (ic) = newcond;
3610 /* first we rule out the boundary conditions */
3611 /* if only optimization says so */
3614 sym_link *cetype = getSpec (operandType (cond));
3615 /* no need to check the lower bound if
3616 the condition is unsigned & minimum value is zero */
3617 if (!(min == 0 && IS_UNSIGNED (cetype)))
3619 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3620 ic = newiCodeCondition (boundary, falseLabel, NULL);
3624 /* now for upper bounds */
3625 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3626 ic = newiCodeCondition (boundary, falseLabel, NULL);
3630 /* if the min is not zero then we no make it zero */
3633 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3634 if (!IS_LITERAL(getSpec(operandType(cond))))
3635 setOperandType (cond, UCHARTYPE);
3638 /* now create the jumptable */
3639 ic = newiCode (JUMPTABLE, NULL, NULL);
3640 IC_JTCOND (ic) = cond;
3641 IC_JTLABELS (ic) = labels;
3646 /*-----------------------------------------------------------------*/
3647 /* geniCodeSwitch - changes a switch to a if statement */
3648 /*-----------------------------------------------------------------*/
3650 geniCodeSwitch (ast * tree,int lvl)
3653 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3654 value *caseVals = tree->values.switchVals.swVals;
3655 symbol *trueLabel, *falseLabel;
3657 /* If the condition is a literal, then just jump to the */
3658 /* appropriate case label. */
3659 if (IS_LITERAL(getSpec(operandType(cond))))
3661 int switchVal, caseVal;
3663 switchVal = (int) floatFromVal (cond->operand.valOperand);
3666 caseVal = (int) floatFromVal (caseVals);
3667 if (caseVal == switchVal)
3669 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3670 tree->values.switchVals.swNum, caseVal);
3671 trueLabel = newiTempLabel (buffer);
3672 geniCodeGoto (trueLabel);
3675 caseVals = caseVals->next;
3677 goto defaultOrBreak;
3680 /* if we can make this a jump table */
3681 if (geniCodeJumpTable (cond, caseVals, tree))
3682 goto jumpTable; /* no need for the comparison */
3684 /* for the cases defined do */
3688 operand *compare = geniCodeLogic (cond,
3689 operandFromValue (caseVals),
3692 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3693 tree->values.switchVals.swNum,
3694 (int) floatFromVal (caseVals));
3695 trueLabel = newiTempLabel (buffer);
3697 ic = newiCodeCondition (compare, trueLabel, NULL);
3699 caseVals = caseVals->next;
3704 /* if default is present then goto break else break */
3705 if (tree->values.switchVals.swDefault)
3707 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3711 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3714 falseLabel = newiTempLabel (buffer);
3715 geniCodeGoto (falseLabel);
3718 ast2iCode (tree->right,lvl+1);
3721 /*-----------------------------------------------------------------*/
3722 /* geniCodeInline - intermediate code for inline assembler */
3723 /*-----------------------------------------------------------------*/
3725 geniCodeInline (ast * tree)
3729 ic = newiCode (INLINEASM, NULL, NULL);
3730 IC_INLINE (ic) = tree->values.inlineasm;
3734 /*-----------------------------------------------------------------*/
3735 /* geniCodeArrayInit - intermediate code for array initializer */
3736 /*-----------------------------------------------------------------*/
3738 geniCodeArrayInit (ast * tree, operand *array)
3742 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3743 ic = newiCode (ARRAYINIT, array, NULL);
3744 IC_ARRAYILIST (ic) = tree->values.constlist;
3746 operand *left=newOperand(), *right=newOperand();
3747 left->type=right->type=SYMBOL;
3748 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3749 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3750 ic = newiCode (ARRAYINIT, left, right);
3755 /*-----------------------------------------------------------------*/
3756 /* geniCodeCritical - intermediate code for a critical statement */
3757 /*-----------------------------------------------------------------*/
3759 geniCodeCritical (ast *tree, int lvl)
3764 /* If op is NULL, the original interrupt state will saved on */
3765 /* the stack. Otherwise, it will be saved in op. */
3767 /* Generate a save of the current interrupt state & disabled */
3768 ic = newiCode (CRITICAL, NULL, NULL);
3769 IC_RESULT (ic) = op;
3772 /* Generate the critical code sequence */
3773 if (tree->left && tree->left->type == EX_VALUE)
3774 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3776 ast2iCode (tree->left,lvl+1);
3778 /* Generate a restore of the original interrupt state */
3779 ic = newiCode (ENDCRITICAL, NULL, op);
3783 /*-----------------------------------------------------------------*/
3784 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3785 /* particular case. Ie : assigning or dereferencing array or ptr */
3786 /*-----------------------------------------------------------------*/
3787 set * lvaluereqSet = NULL;
3788 typedef struct lvalItem
3795 /*-----------------------------------------------------------------*/
3796 /* addLvaluereq - add a flag for lvalreq for current ast level */
3797 /*-----------------------------------------------------------------*/
3798 void addLvaluereq(int lvl)
3800 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3803 addSetHead(&lvaluereqSet,lpItem);
3806 /*-----------------------------------------------------------------*/
3807 /* delLvaluereq - del a flag for lvalreq for current ast level */
3808 /*-----------------------------------------------------------------*/
3812 lpItem = getSet(&lvaluereqSet);
3813 if(lpItem) Safe_free(lpItem);
3815 /*-----------------------------------------------------------------*/
3816 /* clearLvaluereq - clear lvalreq flag */
3817 /*-----------------------------------------------------------------*/
3818 void clearLvaluereq()
3821 lpItem = peekSet(lvaluereqSet);
3822 if(lpItem) lpItem->req = 0;
3824 /*-----------------------------------------------------------------*/
3825 /* getLvaluereq - get the last lvalreq level */
3826 /*-----------------------------------------------------------------*/
3827 int getLvaluereqLvl()
3830 lpItem = peekSet(lvaluereqSet);
3831 if(lpItem) return lpItem->lvl;
3834 /*-----------------------------------------------------------------*/
3835 /* isLvaluereq - is lvalreq valid for this level ? */
3836 /*-----------------------------------------------------------------*/
3837 int isLvaluereq(int lvl)
3840 lpItem = peekSet(lvaluereqSet);
3841 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3845 /*-----------------------------------------------------------------*/
3846 /* ast2iCode - creates an icodeList from an ast */
3847 /*-----------------------------------------------------------------*/
3849 ast2iCode (ast * tree,int lvl)
3851 operand *left = NULL;
3852 operand *right = NULL;
3856 /* set the global variables for filename & line number */
3858 filename = tree->filename;
3860 lineno = tree->lineno;
3862 block = tree->block;
3864 scopeLevel = tree->level;
3866 seqPoint = tree->seqPoint;
3868 if (tree->type == EX_VALUE)
3869 return operandFromValue (tree->opval.val);
3871 if (tree->type == EX_LINK)
3872 return operandFromLink (tree->opval.lnk);
3874 /* if we find a nullop */
3875 if (tree->type == EX_OP &&
3876 (tree->opval.op == NULLOP ||
3877 tree->opval.op == BLOCK))
3879 if (tree->left && tree->left->type == EX_VALUE)
3880 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3882 ast2iCode (tree->left,lvl+1);
3883 if (tree->right && tree->right->type == EX_VALUE)
3884 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3886 ast2iCode (tree->right,lvl+1);
3890 /* special cases for not evaluating */
3891 if (tree->opval.op != ':' &&
3892 tree->opval.op != '?' &&
3893 tree->opval.op != CALL &&
3894 tree->opval.op != IFX &&
3895 tree->opval.op != AND_OP &&
3896 tree->opval.op != OR_OP &&
3897 tree->opval.op != LABEL &&
3898 tree->opval.op != GOTO &&
3899 tree->opval.op != SWITCH &&
3900 tree->opval.op != FUNCTION &&
3901 tree->opval.op != INLINEASM &&
3902 tree->opval.op != CRITICAL)
3905 if (IS_ASSIGN_OP (tree->opval.op) ||
3906 IS_DEREF_OP (tree) ||
3907 (tree->opval.op == '&' && !tree->right) ||
3908 tree->opval.op == PTR_OP)
3911 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3912 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3915 left = operandFromAst (tree->left,lvl);
3917 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3918 left = geniCodeRValue (left, TRUE);
3922 left = operandFromAst (tree->left,lvl);
3924 if (tree->opval.op == INC_OP ||
3925 tree->opval.op == DEC_OP)
3928 right = operandFromAst (tree->right,lvl);
3933 right = operandFromAst (tree->right,lvl);
3937 /* now depending on the type of operand */
3938 /* this will be a biggy */
3939 switch (tree->opval.op)
3942 case '[': /* array operation */
3944 //sym_link *ltype = operandType (left);
3945 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3946 left = geniCodeRValue (left, FALSE);
3947 right = geniCodeRValue (right, TRUE);
3950 return geniCodeArray (left, right,lvl);
3952 case '.': /* structure dereference */
3953 if (IS_PTR (operandType (left)))
3954 left = geniCodeRValue (left, TRUE);
3956 left = geniCodeRValue (left, FALSE);
3958 return geniCodeStruct (left, right, tree->lvalue);
3960 case PTR_OP: /* structure pointer dereference */
3963 pType = operandType (left);
3964 left = geniCodeRValue (left, TRUE);
3966 setOClass (pType, getSpec (operandType (left)));
3969 return geniCodeStruct (left, right, tree->lvalue);
3971 case INC_OP: /* increment operator */
3973 return geniCodePostInc (left);
3975 return geniCodePreInc (right, tree->lvalue);
3977 case DEC_OP: /* decrement operator */
3979 return geniCodePostDec (left);
3981 return geniCodePreDec (right, tree->lvalue);
3983 case '&': /* bitwise and or address of operator */
3985 { /* this is a bitwise operator */
3986 left = geniCodeRValue (left, FALSE);
3987 right = geniCodeRValue (right, FALSE);
3988 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3991 return geniCodeAddressOf (left);
3993 case '|': /* bitwise or & xor */
3995 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3996 geniCodeRValue (right, FALSE),
4001 return geniCodeDivision (geniCodeRValue (left, FALSE),
4002 geniCodeRValue (right, FALSE),
4003 getResultTypeFromType (tree->ftype));
4006 return geniCodeModulus (geniCodeRValue (left, FALSE),
4007 geniCodeRValue (right, FALSE),
4008 getResultTypeFromType (tree->ftype));
4011 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4012 geniCodeRValue (right, FALSE),
4013 getResultTypeFromType (tree->ftype));
4015 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4019 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4020 geniCodeRValue (right, FALSE),
4021 getResultTypeFromType (tree->ftype));
4023 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4027 return geniCodeAdd (geniCodeRValue (left, FALSE),
4028 geniCodeRValue (right, FALSE),
4029 getResultTypeFromType (tree->ftype),
4032 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4035 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4036 geniCodeRValue (right, FALSE),
4037 getResultTypeFromType (tree->ftype));
4040 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4041 geniCodeRValue (right, FALSE));
4043 #if 0 // this indeed needs a second thought
4047 // let's keep this simple: get the rvalue we need
4048 op=geniCodeRValue (right, FALSE);
4049 // now cast it to whatever we want
4050 op=geniCodeCast (operandType(left), op, FALSE);
4051 // if this is going to be used as an lvalue, make it so
4057 #else // bug #604575, is it a bug ????
4058 return geniCodeCast (operandType (left),
4059 geniCodeRValue (right, FALSE), FALSE);
4066 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4071 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4072 setOperandType (op, UCHARTYPE);
4077 return geniCodeLogicAndOr (tree, lvl);
4084 /* different compilers (even different gccs) evaluate
4085 the two calls in a different order. to get the same
4086 result on all machines we've to specify a clear sequence.
4087 return geniCodeLogic (geniCodeRValue (left, FALSE),
4088 geniCodeRValue (right, FALSE),
4092 operand *leftOp, *rightOp;
4094 leftOp = geniCodeRValue (left , FALSE);
4095 rightOp = geniCodeRValue (right, FALSE);
4097 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4100 return geniCodeConditional (tree,lvl);
4103 return operandFromLit (getSize (tree->right->ftype));
4107 sym_link *rtype = operandType (right);
4108 sym_link *ltype = operandType (left);
4109 if (IS_PTR (rtype) && IS_ITEMP (right)
4110 && right->isaddr && compareType (rtype->next, ltype) == 1)
4111 right = geniCodeRValue (right, TRUE);
4113 right = geniCodeRValue (right, FALSE);
4115 geniCodeAssign (left, right, 0, 1);
4120 geniCodeAssign (left,
4121 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4123 geniCodeRValue (right, FALSE),
4124 getResultTypeFromType (tree->ftype)),
4129 geniCodeAssign (left,
4130 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4132 geniCodeRValue (right, FALSE),
4133 getResultTypeFromType (tree->ftype)),
4137 geniCodeAssign (left,
4138 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4140 geniCodeRValue (right, FALSE),
4141 getResultTypeFromType (tree->ftype)),
4145 sym_link *rtype = operandType (right);
4146 sym_link *ltype = operandType (left);
4147 if (IS_PTR (rtype) && IS_ITEMP (right)
4148 && right->isaddr && compareType (rtype->next, ltype) == 1)
4149 right = geniCodeRValue (right, TRUE);
4151 right = geniCodeRValue (right, FALSE);
4154 return geniCodeAssign (left,
4155 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4158 getResultTypeFromType (tree->ftype),
4164 sym_link *rtype = operandType (right);
4165 sym_link *ltype = operandType (left);
4166 if (IS_PTR (rtype) && IS_ITEMP (right)
4167 && right->isaddr && compareType (rtype->next, ltype) == 1)
4169 right = geniCodeRValue (right, TRUE);
4173 right = geniCodeRValue (right, FALSE);
4176 geniCodeAssign (left,
4177 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4180 getResultTypeFromType (tree->ftype)),
4185 geniCodeAssign (left,
4186 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4188 geniCodeRValue (right, FALSE),
4189 getResultTypeFromType (tree->ftype)),
4193 geniCodeAssign (left,
4194 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4196 geniCodeRValue (right, FALSE)), 0, 1);
4199 geniCodeAssign (left,
4200 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4202 geniCodeRValue (right, FALSE),
4204 operandType (left)), 0, 1);
4207 geniCodeAssign (left,
4208 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4210 geniCodeRValue (right, FALSE),
4212 operandType (left)), 0, 1);
4215 geniCodeAssign (left,
4216 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4218 geniCodeRValue (right, FALSE),
4220 operandType (left)), 0, 1);
4222 return geniCodeRValue (right, FALSE);
4225 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4228 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4229 return ast2iCode (tree->right,lvl+1);
4232 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4233 return ast2iCode (tree->right,lvl+1);
4236 geniCodeFunctionBody (tree,lvl);
4240 geniCodeReturn (right);
4244 geniCodeIfx (tree,lvl);
4248 geniCodeSwitch (tree,lvl);
4252 geniCodeInline (tree);
4256 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4260 geniCodeCritical (tree, lvl);
4266 /*-----------------------------------------------------------------*/
4267 /* reverseICChain - gets from the list and creates a linkedlist */
4268 /*-----------------------------------------------------------------*/
4275 while ((loop = getSet (&iCodeChain)))
4287 /*-----------------------------------------------------------------*/
4288 /* iCodeFromAst - given an ast will convert it to iCode */
4289 /*-----------------------------------------------------------------*/
4291 iCodeFromAst (ast * tree)
4293 returnLabel = newiTempLabel ("_return");
4294 entryLabel = newiTempLabel ("_entry");
4296 return reverseiCChain ();
4299 static const char *opTypeToStr(OPTYPE op)
4303 case SYMBOL: return "symbol";
4304 case VALUE: return "value";
4305 case TYPE: return "type";
4307 return "undefined type";
4311 operand *validateOpType(operand *op,
4318 if (op && op->type == type)
4323 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4324 " expected %s, got %s\n",
4325 macro, args, file, line,
4326 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4328 return op; // never reached, makes compiler happy.