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_FIXED(ltype)) {
179 if (!IS_UNSIGNED(val->type) && v<0) {
181 if (IS_UNSIGNED(ltype) && (pedantic>1)) {
187 // if very pedantic: "char c=200" is not allowed
188 if (pedantic>1 && !IS_UNSIGNED(ltype)) {
189 max = max/2 + negative;
196 #if 0 // temporary disabled, leaving the warning as a reminder
198 SNPRINTF (message, sizeof(message), "for %s %s in %s",
199 IS_UNSIGNED(ltype) ? "unsigned" : "signed",
200 nounName(ltype), msg);
201 werror (W_CONST_RANGE, message);
209 /*-----------------------------------------------------------------*/
210 /* operandName - returns the name of the operand */
211 /*-----------------------------------------------------------------*/
213 printOperand (operand * op, FILE * file)
230 opetype = getSpec (operandType (op));
231 if (IS_FLOAT (opetype))
232 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
233 if (IS_FIXED16X16 (opetype))
234 fprintf (file, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
236 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
237 printTypeChain (operandType (op), file);
244 if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
245 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
246 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
248 OP_LIVEFROM (op), OP_LIVETO (op),
249 OP_SYMBOL (op)->stack,
250 op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
251 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
252 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
256 printTypeChain (operandType (op), file);
257 if (SPIL_LOC (op) && IS_ITEMP (op))
258 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
263 /* if assigned to registers */
264 if (OP_SYMBOL (op)->nRegs)
266 if (OP_SYMBOL (op)->isspilt)
268 if (!OP_SYMBOL (op)->remat)
269 if (OP_SYMBOL (op)->usl.spillLoc)
270 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
271 OP_SYMBOL (op)->usl.spillLoc->rname :
272 OP_SYMBOL (op)->usl.spillLoc->name));
274 fprintf (file, "[err]");
276 fprintf (file, "[remat]");
282 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
283 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
287 //#else /* } else { */
289 /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
290 fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
292 if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
294 fprintf (file, "[lr%d:%d so:%d]",
295 OP_LIVEFROM (op), OP_LIVETO (op),
296 OP_SYMBOL (op)->stack);
299 if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
302 printTypeChain (operandType (op), file);
303 if (SPIL_LOC (op) && IS_ITEMP (op))
304 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
308 /* if assigned to registers */
309 if (OP_SYMBOL (op)->nRegs)
311 if (OP_SYMBOL (op)->isspilt)
313 if (!OP_SYMBOL (op)->remat)
314 if (OP_SYMBOL (op)->usl.spillLoc)
315 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
316 OP_SYMBOL (op)->usl.spillLoc->rname :
317 OP_SYMBOL (op)->usl.spillLoc->name));
319 fprintf (file, "[err]");
321 fprintf (file, "[remat]");
327 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
328 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
338 printTypeChain (op->operand.typeOperand, file);
344 fprintf (file, "\n");
349 /*-----------------------------------------------------------------*/
350 /* print functions */
351 /*-----------------------------------------------------------------*/
352 PRINTFUNC (picGetValueAtAddr)
355 printOperand (IC_RESULT (ic), of);
358 printOperand (IC_LEFT (ic), of);
364 PRINTFUNC (picSetValueAtAddr)
368 printOperand (IC_LEFT (ic), of);
369 fprintf (of, "] = ");
370 printOperand (IC_RIGHT (ic), of);
374 PRINTFUNC (picAddrOf)
377 printOperand (IC_RESULT (ic), of);
378 if (IS_ITEMP (IC_LEFT (ic)))
381 fprintf (of, " = &[");
382 printOperand (IC_LEFT (ic), of);
385 if (IS_ITEMP (IC_LEFT (ic)))
386 fprintf (of, " offsetAdd ");
389 printOperand (IC_RIGHT (ic), of);
391 if (IS_ITEMP (IC_LEFT (ic)))
397 PRINTFUNC (picJumpTable)
402 fprintf (of, "%s\t", s);
403 printOperand (IC_JTCOND (ic), of);
405 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
406 sym = setNextItem (IC_JTLABELS (ic)))
407 fprintf (of, "\t\t\t%s\n", sym->name);
410 PRINTFUNC (picGeneric)
413 printOperand (IC_RESULT (ic), of);
415 printOperand (IC_LEFT (ic), of);
416 fprintf (of, " %s ", s);
417 printOperand (IC_RIGHT (ic), of);
421 PRINTFUNC (picGenericOne)
426 printOperand (IC_RESULT (ic), of);
432 fprintf (of, "%s ", s);
433 printOperand (IC_LEFT (ic), of);
436 if (!IC_RESULT (ic) && !IC_LEFT (ic))
439 if (ic->op == SEND || ic->op == RECEIVE) {
440 fprintf(of,"{argreg = %d}",ic->argreg);
442 if (ic->op == IPUSH) {
443 fprintf(of,"{parmPush = %d}",ic->parmPush);
451 printOperand (IC_RESULT (ic), of);
453 printOperand (IC_LEFT (ic), of);
454 printOperand (IC_RIGHT (ic), of);
459 PRINTFUNC (picAssign)
463 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
466 printOperand (IC_RESULT (ic), of);
468 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
471 fprintf (of, " %s ", s);
472 printOperand (IC_RIGHT (ic), of);
479 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
485 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
492 printOperand (IC_COND (ic), of);
495 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
498 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
500 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
504 PRINTFUNC (picInline)
506 fprintf (of, "%s", IC_INLINE (ic));
509 PRINTFUNC (picReceive)
511 printOperand (IC_RESULT (ic), of);
512 fprintf (of, " = %s ", s);
513 printOperand (IC_LEFT (ic), of);
517 PRINTFUNC (picDummyRead)
520 fprintf (of, "%s ", s);
521 printOperand (IC_RIGHT (ic), of);
525 PRINTFUNC (picCritical)
529 printOperand (IC_RESULT (ic), of);
531 fprintf (of, "(stack)");
532 fprintf (of, " = %s ", s);
536 PRINTFUNC (picEndCritical)
539 fprintf (of, "%s = ", s);
541 printOperand (IC_RIGHT (ic), of);
543 fprintf (of, "(stack)");
547 /*-----------------------------------------------------------------*/
548 /* piCode - prints one iCode */
549 /*-----------------------------------------------------------------*/
551 piCode (void *item, FILE * of)
559 icTab = getTableEntry (ic->op);
560 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
561 ic->filename, ic->lineno,
562 ic->seq, ic->key, ic->depth, ic->supportRtn);
563 icTab->iCodePrint (of, ic, icTab->printName);
569 printiCChain(ic,stdout);
571 /*-----------------------------------------------------------------*/
572 /* printiCChain - prints intermediate code for humans */
573 /*-----------------------------------------------------------------*/
575 printiCChain (iCode * icChain, FILE * of)
582 for (loop = icChain; loop; loop = loop->next)
584 if ((icTab = getTableEntry (loop->op)))
586 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
587 loop->filename, loop->lineno,
588 loop->seq, loop->key, loop->depth, loop->supportRtn);
590 icTab->iCodePrint (of, loop, icTab->printName);
596 /*-----------------------------------------------------------------*/
597 /* newOperand - allocate, init & return a new iCode */
598 /*-----------------------------------------------------------------*/
604 op = Safe_alloc ( sizeof (operand));
610 /*-----------------------------------------------------------------*/
611 /* newiCode - create and return a new iCode entry initialised */
612 /*-----------------------------------------------------------------*/
614 newiCode (int op, operand * left, operand * right)
618 ic = Safe_alloc ( sizeof (iCode));
620 ic->seqPoint = seqPoint;
622 ic->filename = filename;
624 ic->level = scopeLevel;
626 ic->key = iCodeKey++;
628 IC_RIGHT (ic) = right;
633 /*-----------------------------------------------------------------*/
634 /* newiCode for conditional statements */
635 /*-----------------------------------------------------------------*/
637 newiCodeCondition (operand * condition,
643 if (IS_VOID(operandType(condition))) {
644 werror(E_VOID_VALUE_USED);
647 ic = newiCode (IFX, NULL, NULL);
648 IC_COND (ic) = condition;
649 IC_TRUE (ic) = trueLabel;
650 IC_FALSE (ic) = falseLabel;
654 /*-----------------------------------------------------------------*/
655 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
656 /*-----------------------------------------------------------------*/
658 newiCodeLabelGoto (int op, symbol * label)
662 ic = newiCode (op, NULL, NULL);
666 IC_RIGHT (ic) = NULL;
667 IC_RESULT (ic) = NULL;
671 /*-----------------------------------------------------------------*/
672 /* newiTemp - allocate & return a newItemp Variable */
673 /*-----------------------------------------------------------------*/
681 SNPRINTF (buffer, sizeof(buffer), "%s", s);
685 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
688 itmp = newSymbol (buffer, 1);
689 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
695 /*-----------------------------------------------------------------*/
696 /* newiTempLabel - creates a temp variable label */
697 /*-----------------------------------------------------------------*/
699 newiTempLabel (char *s)
703 /* check if this already exists */
704 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
709 itmplbl = newSymbol (s, 1);
713 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
714 itmplbl = newSymbol (buffer, 1);
719 itmplbl->key = labelKey++;
720 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
724 /*-----------------------------------------------------------------*/
725 /* newiTempPreheaderLabel - creates a new preheader label */
726 /*-----------------------------------------------------------------*/
728 newiTempPreheaderLabel ()
732 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
733 itmplbl = newSymbol (buffer, 1);
737 itmplbl->key = labelKey++;
738 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
743 /*-----------------------------------------------------------------*/
744 /* initiCode - initialises some iCode related stuff */
745 /*-----------------------------------------------------------------*/
752 /*-----------------------------------------------------------------*/
753 /* copyiCode - make a copy of the iCode given */
754 /*-----------------------------------------------------------------*/
756 copyiCode (iCode * ic)
758 iCode *nic = newiCode (ic->op, NULL, NULL);
760 nic->lineno = ic->lineno;
761 nic->filename = ic->filename;
762 nic->block = ic->block;
763 nic->level = ic->level;
764 nic->parmBytes = ic->parmBytes;
766 /* deal with the special cases first */
770 IC_COND (nic) = operandFromOperand (IC_COND (ic));
771 IC_TRUE (nic) = IC_TRUE (ic);
772 IC_FALSE (nic) = IC_FALSE (ic);
776 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
777 IC_JTLABELS (nic) = IC_JTLABELS (ic);
782 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
783 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
787 IC_INLINE (nic) = IC_INLINE (ic);
791 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
795 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
796 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
797 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
803 /*-----------------------------------------------------------------*/
804 /* getTableEntry - gets the table entry for the given operator */
805 /*-----------------------------------------------------------------*/
807 getTableEntry (int oper)
811 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
812 if (oper == codeTable[i].icode)
813 return &codeTable[i];
818 /*-----------------------------------------------------------------*/
819 /* newiTempOperand - new intermediate temp operand */
820 /*-----------------------------------------------------------------*/
822 newiTempOperand (sym_link * type, char throwType)
825 operand *op = newOperand ();
829 itmp = newiTemp (NULL);
831 etype = getSpec (type);
833 if (IS_LITERAL (etype))
836 /* copy the type information */
838 itmp->etype = getSpec (itmp->type = (throwType ? type :
839 copyLinkChain (type)));
840 if (IS_LITERAL (itmp->etype))
842 SPEC_SCLS (itmp->etype) = S_REGISTER;
843 SPEC_OCLS (itmp->etype) = reg;
846 op->operand.symOperand = itmp;
847 op->key = itmp->key = ++operandKey;
851 /*-----------------------------------------------------------------*/
852 /* operandType - returns the type chain for an operand */
853 /*-----------------------------------------------------------------*/
855 operandType (operand * op)
857 /* depending on type of operand */
862 return op->operand.valOperand->type;
865 return op->operand.symOperand->type;
868 return op->operand.typeOperand;
870 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
871 " operand type not known ");
872 assert (0); /* should never come here */
873 /* Just to keep the compiler happy */
874 return (sym_link *) 0;
878 /*-----------------------------------------------------------------*/
879 /* isParamterToCall - will return 1 if op is a parameter to args */
880 /*-----------------------------------------------------------------*/
882 isParameterToCall (value * args, operand * op)
886 wassert (IS_SYMOP(op));
891 isSymbolEqual (op->operand.symOperand, tval->sym))
898 /*-----------------------------------------------------------------*/
899 /* isOperandGlobal - return 1 if operand is a global variable */
900 /*-----------------------------------------------------------------*/
902 isOperandGlobal (operand * op)
911 (op->operand.symOperand->level == 0 ||
912 IS_STATIC (op->operand.symOperand->etype) ||
913 IS_EXTERN (op->operand.symOperand->etype))
920 /*-----------------------------------------------------------------*/
921 /* isOperandVolatile - return 1 if the operand is volatile */
922 /*-----------------------------------------------------------------*/
924 isOperandVolatile (operand * op, bool chkTemp)
929 if (IS_ITEMP (op) && !chkTemp)
932 opetype = getSpec (optype = operandType (op));
934 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
937 if (IS_VOLATILE (opetype))
942 /*-----------------------------------------------------------------*/
943 /* isOperandLiteral - returns 1 if an operand contains a literal */
944 /*-----------------------------------------------------------------*/
946 isOperandLiteral (operand * op)
953 opetype = getSpec (operandType (op));
955 if (IS_LITERAL (opetype))
961 /*-----------------------------------------------------------------*/
962 /* isOperandInFarSpace - will return true if operand is in farSpace */
963 /*-----------------------------------------------------------------*/
965 isOperandInFarSpace (operand * op)
975 if (!IS_TRUE_SYMOP (op))
978 etype = SPIL_LOC (op)->etype;
984 etype = getSpec (operandType (op));
986 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
989 /*------------------------------------------------------------------*/
990 /* isOperandInDirSpace - will return true if operand is in dirSpace */
991 /*------------------------------------------------------------------*/
993 isOperandInDirSpace (operand * op)
1003 if (!IS_TRUE_SYMOP (op))
1006 etype = SPIL_LOC (op)->etype;
1012 etype = getSpec (operandType (op));
1014 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1017 /*--------------------------------------------------------------------*/
1018 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
1019 /*--------------------------------------------------------------------*/
1021 isOperandInCodeSpace (operand * op)
1031 etype = getSpec (operandType (op));
1033 if (!IS_TRUE_SYMOP (op))
1036 etype = SPIL_LOC (op)->etype;
1042 etype = getSpec (operandType (op));
1044 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1047 /*-----------------------------------------------------------------*/
1048 /* isOperandOnStack - will return true if operand is on stack */
1049 /*-----------------------------------------------------------------*/
1051 isOperandOnStack (operand * op)
1061 etype = getSpec (operandType (op));
1062 if (IN_STACK (etype) ||
1063 OP_SYMBOL(op)->onStack ||
1064 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1070 /*-----------------------------------------------------------------*/
1071 /* isOclsExpensive - will return true if accesses to an output */
1072 /* storage class are expensive */
1073 /*-----------------------------------------------------------------*/
1075 isOclsExpensive (struct memmap *oclass)
1077 if (port->oclsExpense)
1078 return port->oclsExpense (oclass) > 0;
1080 /* In the absence of port specific guidance, assume only */
1081 /* farspace is expensive. */
1082 return IN_FARSPACE (oclass);
1085 /*-----------------------------------------------------------------*/
1086 /* isiCodeInFunctionCall - return TRUE if an iCode is between a */
1087 /* CALL/PCALL and the first IPUSH/SEND associated with the call */
1088 /*-----------------------------------------------------------------*/
1090 isiCodeInFunctionCall (iCode * ic)
1094 /* Find the next CALL/PCALL */
1097 if (lic->op == CALL || lic->op == PCALL)
1105 /* A function call was found. Scan backwards and see if an */
1106 /* IPUSH or SEND is encountered */
1109 if (lic != ic && (ic->op == CALL || ic->op == PCALL))
1111 if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
1119 /*-----------------------------------------------------------------*/
1120 /* operandLitValue - literal value of an operand */
1121 /*-----------------------------------------------------------------*/
1123 operandLitValue (operand * op)
1125 assert (isOperandLiteral (op));
1127 return floatFromVal (op->operand.valOperand);
1130 /*-----------------------------------------------------------------*/
1131 /* getBuiltInParms - returns parameters to a builtin functions */
1132 /*-----------------------------------------------------------------*/
1133 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1138 /* builtin functions uses only SEND for parameters */
1139 while (ic->op != CALL) {
1140 assert(ic->op == SEND && ic->builtinSEND);
1141 ic->generated = 1; /* mark the icode as generated */
1142 parms[*pcount] = IC_LEFT(ic);
1148 /* make sure this is a builtin function call */
1149 assert(IS_SYMOP(IC_LEFT(ic)));
1150 ftype = operandType(IC_LEFT(ic));
1151 assert(IFFUNC_ISBUILTIN(ftype));
1155 /*-----------------------------------------------------------------*/
1156 /* operandOperation - performs operations on operands */
1157 /*-----------------------------------------------------------------*/
1159 operandOperation (operand * left, operand * right,
1160 int op, sym_link * type)
1162 sym_link *let , *ret=NULL;
1163 operand *retval = (operand *) 0;
1165 assert (isOperandLiteral (left));
1166 let = getSpec(operandType(left));
1168 assert (isOperandLiteral (right));
1169 ret = getSpec(operandType(right));
1175 retval = operandFromValue (valCastLiteral (type,
1176 operandLitValue (left) +
1177 operandLitValue (right)));
1180 retval = operandFromValue (valCastLiteral (type,
1181 operandLitValue (left) -
1182 operandLitValue (right)));
1186 retval = operandFromValue (valCastLiteral (type,
1187 operandLitValue (left) *
1188 operandLitValue (right)));
1189 This could be all we've to do, but with gcc we've to take care about
1190 overflows. Two examples:
1191 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1192 significant bits are lost (52 in fraction, 63 bits would be
1193 necessary to keep full precision).
1194 If the resulting double value is greater than ULONG_MAX (resp.
1195 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1198 /* if it is not a specifier then we can assume that */
1199 /* it will be an unsigned long */
1200 if (IS_INT (type) ||
1203 /* long is handled here, because it can overflow with double */
1204 if (IS_LONG (type) ||
1206 /* signed and unsigned mul are the same, as long as the precision
1207 of the result isn't bigger than the precision of the operands. */
1208 retval = operandFromValue (valCastLiteral (type,
1209 (TYPE_UDWORD) operandLitValue (left) *
1210 (TYPE_UDWORD) operandLitValue (right)));
1211 else if (IS_UNSIGNED (type)) /* unsigned int */
1213 /* unsigned int is handled here in order to detect overflow */
1214 TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
1215 (TYPE_UWORD) operandLitValue (right);
1217 retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
1218 if (ul != (TYPE_UWORD) ul)
1221 else /* signed int */
1223 /* signed int is handled here in order to detect overflow */
1224 TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
1225 (TYPE_WORD) operandLitValue (right);
1227 retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
1228 if (l != (TYPE_WORD) l)
1233 /* all others go here: */
1234 retval = operandFromValue (valCastLiteral (type,
1235 operandLitValue (left) *
1236 operandLitValue (right)));
1239 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1241 werror (E_DIVIDE_BY_ZERO);
1247 if (IS_UNSIGNED (type))
1249 SPEC_USIGN (let) = 1;
1250 SPEC_USIGN (ret) = 1;
1251 retval = operandFromValue (valCastLiteral (type,
1252 (TYPE_UDWORD) operandLitValue (left) /
1253 (TYPE_UDWORD) operandLitValue (right)));
1257 retval = operandFromValue (valCastLiteral (type,
1258 operandLitValue (left) /
1259 operandLitValue (right)));
1264 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1266 werror (E_DIVIDE_BY_ZERO);
1271 if (IS_UNSIGNED (type))
1272 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1273 (TYPE_UDWORD) operandLitValue (right));
1275 retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1276 (TYPE_DWORD) operandLitValue (right));
1280 /* The number of left shifts is always unsigned. Signed doesn't make
1281 sense here. Shifting by a negative number is impossible. */
1282 retval = operandFromValue (valCastLiteral (type,
1283 ((TYPE_UDWORD) operandLitValue (left) <<
1284 (TYPE_UDWORD) operandLitValue (right))));
1287 /* The number of right shifts is always unsigned. Signed doesn't make
1288 sense here. Shifting by a negative number is impossible. */
1289 if (IS_UNSIGNED(let))
1290 /* unsigned: logic shift right */
1291 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1292 (TYPE_UDWORD) operandLitValue (right));
1294 /* signed: arithmetic shift right */
1295 retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1296 (TYPE_UDWORD) operandLitValue (right));
1299 if (IS_FLOAT (let) ||
1302 retval = operandFromLit (operandLitValue (left) ==
1303 operandLitValue (right));
1306 if (IS_FIXED16X16 (let) ||
1307 IS_FIXED16X16 (ret))
1309 retval = operandFromLit (operandLitValue (left) ==
1310 operandLitValue (right));
1314 /* this op doesn't care about signedness */
1317 l = (TYPE_UDWORD) operandLitValue (left);
1318 r = (TYPE_UDWORD) operandLitValue (right);
1319 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1320 neccessary to strip them to 16 bit.
1321 Literals are reduced to their cheapest type, therefore left and
1322 right might have different types. It's neccessary to find a
1323 common type: int (used for char too) or long */
1324 if (!IS_LONG (let) &&
1330 retval = operandFromLit (l == r);
1334 retval = operandFromLit (operandLitValue (left) <
1335 operandLitValue (right));
1338 retval = operandFromLit (operandLitValue (left) <=
1339 operandLitValue (right));
1342 retval = operandFromLit (operandLitValue (left) !=
1343 operandLitValue (right));
1346 retval = operandFromLit (operandLitValue (left) >
1347 operandLitValue (right));
1350 retval = operandFromLit (operandLitValue (left) >=
1351 operandLitValue (right));
1354 retval = operandFromValue (valCastLiteral (type,
1355 (TYPE_UDWORD)operandLitValue(left) &
1356 (TYPE_UDWORD)operandLitValue(right)));
1359 retval = operandFromValue (valCastLiteral (type,
1360 (TYPE_UDWORD)operandLitValue(left) |
1361 (TYPE_UDWORD)operandLitValue(right)));
1364 retval = operandFromValue (valCastLiteral (type,
1365 (TYPE_UDWORD)operandLitValue(left) ^
1366 (TYPE_UDWORD)operandLitValue(right)));
1369 retval = operandFromLit (operandLitValue (left) &&
1370 operandLitValue (right));
1373 retval = operandFromLit (operandLitValue (left) ||
1374 operandLitValue (right));
1378 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1380 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1386 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1388 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1394 retval = operandFromValue (valCastLiteral (type,
1395 -1 * operandLitValue (left)));
1399 retval = operandFromValue (valCastLiteral (type,
1401 operandLitValue (left))));
1405 retval = operandFromLit (!operandLitValue (left));
1409 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1410 " operandOperation invalid operator ");
1418 /*-----------------------------------------------------------------*/
1419 /* isOperandEqual - compares two operand & return 1 if they r = */
1420 /*-----------------------------------------------------------------*/
1422 isOperandEqual (operand * left, operand * right)
1424 /* if the pointers are equal then they are equal */
1428 /* if either of them null then false */
1429 if (!left || !right)
1432 if (left->type != right->type)
1435 if (IS_SYMOP (left) && IS_SYMOP (right))
1436 return left->key == right->key;
1438 /* if types are the same */
1442 return isSymbolEqual (left->operand.symOperand,
1443 right->operand.symOperand);
1445 return (compareType (left->operand.valOperand->type,
1446 right->operand.valOperand->type) &&
1447 (floatFromVal (left->operand.valOperand) ==
1448 floatFromVal (right->operand.valOperand)));
1450 if (compareType (left->operand.typeOperand,
1451 right->operand.typeOperand) == 1)
1458 /*-------------------------------------------------------------------*/
1459 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1460 /*-------------------------------------------------------------------*/
1462 isiCodeEqual (iCode * left, iCode * right)
1464 /* if the same pointer */
1468 /* if either of them null */
1469 if (!left || !right)
1472 /* if operand are the same */
1473 if (left->op == right->op)
1476 /* compare all the elements depending on type */
1477 if (left->op != IFX)
1479 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1481 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1487 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1489 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1491 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1500 /*-----------------------------------------------------------------*/
1501 /* newiTempFromOp - create a temp Operand with same attributes */
1502 /*-----------------------------------------------------------------*/
1504 newiTempFromOp (operand * op)
1514 nop = newiTempOperand (operandType (op), TRUE);
1515 nop->isaddr = op->isaddr;
1516 nop->isvolatile = op->isvolatile;
1517 nop->isGlobal = op->isGlobal;
1518 nop->isLiteral = op->isLiteral;
1519 nop->usesDefs = op->usesDefs;
1520 nop->isParm = op->isParm;
1524 /*-----------------------------------------------------------------*/
1525 /* operand from operand - creates an operand holder for the type */
1526 /*-----------------------------------------------------------------*/
1528 operandFromOperand (operand * op)
1534 nop = newOperand ();
1535 nop->type = op->type;
1536 nop->isaddr = op->isaddr;
1538 nop->isvolatile = op->isvolatile;
1539 nop->isGlobal = op->isGlobal;
1540 nop->isLiteral = op->isLiteral;
1541 nop->usesDefs = op->usesDefs;
1542 nop->isParm = op->isParm;
1547 nop->operand.symOperand = op->operand.symOperand;
1550 nop->operand.valOperand = op->operand.valOperand;
1553 nop->operand.typeOperand = op->operand.typeOperand;
1560 /*-----------------------------------------------------------------*/
1561 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1562 /*-----------------------------------------------------------------*/
1564 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1566 operand *nop = operandFromOperand (op);
1568 if (nop->type == SYMBOL)
1570 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1571 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1577 /*-----------------------------------------------------------------*/
1578 /* operandFromSymbol - creates an operand from a symbol */
1579 /*-----------------------------------------------------------------*/
1581 operandFromSymbol (symbol * sym)
1586 /* if the symbol's type is a literal */
1587 /* then it is an enumerator type */
1588 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1589 return operandFromValue (valFromType (sym->etype));
1592 sym->key = ++operandKey;
1594 /* if this an implicit variable, means struct/union */
1595 /* member so just return it */
1596 if (sym->implicit || IS_FUNC (sym->type))
1600 op->operand.symOperand = sym;
1602 op->isvolatile = isOperandVolatile (op, TRUE);
1603 op->isGlobal = isOperandGlobal (op);
1607 /* under the following conditions create a
1608 register equivalent for a local symbol */
1609 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1610 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1612 (!(options.model == MODEL_FLAT24)) ) &&
1613 options.stackAuto == 0)
1616 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1617 !IS_FUNC (sym->type) && /* not a function */
1618 !sym->_isparm && /* not a parameter */
1619 IS_AUTO (sym) && /* is a local auto variable */
1620 !sym->addrtaken && /* whose address has not been taken */
1621 !sym->reqv && /* does not already have a reg equivalence */
1622 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1623 !sym->islbl && /* not a label */
1624 ok && /* farspace check */
1625 !IS_BITVAR (sym->etype) /* not a bit variable */
1629 /* we will use it after all optimizations
1630 and before liveRange calculation */
1631 sym->reqv = newiTempOperand (sym->type, 0);
1632 sym->reqv->key = sym->key;
1633 OP_SYMBOL (sym->reqv)->prereqv = sym;
1634 OP_SYMBOL (sym->reqv)->key = sym->key;
1635 OP_SYMBOL (sym->reqv)->isreqv = 1;
1636 OP_SYMBOL (sym->reqv)->islocal = 1;
1637 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1638 SPIL_LOC (sym->reqv) = sym;
1641 if (!IS_AGGREGATE (sym->type))
1645 op->operand.symOperand = sym;
1648 op->isvolatile = isOperandVolatile (op, TRUE);
1649 op->isGlobal = isOperandGlobal (op);
1650 op->isPtr = IS_PTR (operandType (op));
1651 op->isParm = sym->_isparm;
1656 /* itemp = &[_symbol] */
1658 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1659 IC_LEFT (ic)->type = SYMBOL;
1660 IC_LEFT (ic)->operand.symOperand = sym;
1661 IC_LEFT (ic)->key = sym->key;
1662 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1663 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1664 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1667 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1668 if (IS_ARRAY (sym->type))
1670 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1671 IC_RESULT (ic)->isaddr = 0;
1674 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1678 return IC_RESULT (ic);
1681 /*-----------------------------------------------------------------*/
1682 /* operandFromValue - creates an operand from value */
1683 /*-----------------------------------------------------------------*/
1685 operandFromValue (value * val)
1689 /* if this is a symbol then do the symbol thing */
1691 return operandFromSymbol (val->sym);
1693 /* this is not a symbol */
1696 op->operand.valOperand = val;
1697 op->isLiteral = isOperandLiteral (op);
1701 /*-----------------------------------------------------------------*/
1702 /* operandFromLink - operand from typeChain */
1703 /*-----------------------------------------------------------------*/
1705 operandFromLink (sym_link * type)
1709 /* operand from sym_link */
1715 op->operand.typeOperand = copyLinkChain (type);
1719 /*-----------------------------------------------------------------*/
1720 /* operandFromLit - makes an operand from a literal value */
1721 /*-----------------------------------------------------------------*/
1723 operandFromLit (double i)
1725 return operandFromValue (valueFromLit (i));
1728 /*-----------------------------------------------------------------*/
1729 /* operandFromAst - creates an operand from an ast */
1730 /*-----------------------------------------------------------------*/
1732 operandFromAst (ast * tree,int lvl)
1738 /* depending on type do */
1742 return ast2iCode (tree,lvl+1);
1746 return operandFromValue (tree->opval.val);
1750 return operandFromLink (tree->opval.lnk);
1757 /* Just to keep the compiler happy */
1758 return (operand *) 0;
1761 /*-----------------------------------------------------------------*/
1762 /* setOperandType - sets the operand's type to the given type */
1763 /*-----------------------------------------------------------------*/
1765 setOperandType (operand * op, sym_link * type)
1767 /* depending on the type of operand */
1772 op->operand.valOperand->etype =
1773 getSpec (op->operand.valOperand->type =
1774 copyLinkChain (type));
1778 if (op->operand.symOperand->isitmp)
1779 op->operand.symOperand->etype =
1780 getSpec (op->operand.symOperand->type =
1781 copyLinkChain (type));
1783 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1784 "attempt to modify type of source");
1788 op->operand.typeOperand = copyLinkChain (type);
1794 /*-----------------------------------------------------------------*/
1795 /* Get size in byte of ptr need to access an array */
1796 /*-----------------------------------------------------------------*/
1798 getArraySizePtr (operand * op)
1800 sym_link *ltype = operandType(op);
1804 int size = getSize(ltype);
1805 return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1810 sym_link *letype = getSpec(ltype);
1811 switch (PTR_TYPE (SPEC_OCLS (letype)))
1823 if (GPTRSIZE > FPTRSIZE)
1824 return (GPTRSIZE-1);
1835 /*-----------------------------------------------------------------*/
1836 /* perform "usual unary conversions" */
1837 /*-----------------------------------------------------------------*/
1840 usualUnaryConversions (operand * op)
1842 if (IS_INTEGRAL (operandType (op)))
1844 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1847 return geniCodeCast (INTTYPE, op, TRUE);
1854 /*-----------------------------------------------------------------*/
1855 /* perform "usual binary conversions" */
1856 /*-----------------------------------------------------------------*/
1859 usualBinaryConversions (operand ** op1, operand ** op2,
1860 RESULT_TYPE resultType, int op)
1863 sym_link *rtype = operandType (*op2);
1864 sym_link *ltype = operandType (*op1);
1866 ctype = computeType (ltype, rtype, resultType, op);
1873 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1875 /* one byte operations: keep signedness for code generator */
1883 *op1 = geniCodeCast (ctype, *op1, TRUE);
1884 *op2 = geniCodeCast (ctype, *op2, TRUE);
1889 /*-----------------------------------------------------------------*/
1890 /* geniCodeValueAtAddress - generate intermeditate code for value */
1892 /*-----------------------------------------------------------------*/
1894 geniCodeRValue (operand * op, bool force)
1897 sym_link *type = operandType (op);
1898 sym_link *etype = getSpec (type);
1900 /* if this is an array & already */
1901 /* an address then return this */
1902 if (IS_AGGREGATE (type) ||
1903 (IS_PTR (type) && !force && !op->isaddr))
1904 return operandFromOperand (op);
1906 /* if this is not an address then must be */
1907 /* rvalue already so return this one */
1911 /* if this is not a temp symbol then */
1912 if (!IS_ITEMP (op) &&
1914 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1916 op = operandFromOperand (op);
1921 if (IS_SPEC (type) &&
1922 IS_TRUE_SYMOP (op) &&
1923 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1924 (options.model == MODEL_FLAT24) ))
1926 op = operandFromOperand (op);
1931 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1932 if (IS_PTR (type) && op->isaddr && force)
1935 type = copyLinkChain (type);
1937 IC_RESULT (ic) = newiTempOperand (type, 1);
1938 IC_RESULT (ic)->isaddr = 0;
1940 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1944 return IC_RESULT (ic);
1947 /*-----------------------------------------------------------------*/
1948 /* geniCodeCast - changes the value from one type to another */
1949 /*-----------------------------------------------------------------*/
1951 geniCodeCast (sym_link * type, operand * op, bool implicit)
1955 sym_link *opetype = getSpec (optype = operandType (op));
1959 /* one of them has size zero then error */
1960 if (IS_VOID (optype))
1962 werror (E_CAST_ZERO);
1966 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1968 geniCodeArray2Ptr (op);
1972 /* if the operand is already the desired type then do nothing */
1973 if (compareType (type, optype) == 1)
1976 /* if this is a literal then just change the type & return */
1977 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1979 return operandFromValue (valCastLiteral (type,
1980 operandLitValue (op)));
1983 /* if casting to/from pointers, do some checking */
1984 if (IS_PTR(type)) { // to a pointer
1985 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1986 if (IS_INTEGRAL(optype)) {
1987 // maybe this is NULL, than it's ok.
1988 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1989 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1990 // no way to set the storage
1991 if (IS_LITERAL(optype)) {
1992 werror(E_LITERAL_GENERIC);
1995 werror(E_NONPTR2_GENPTR);
1998 } else if (implicit) {
1999 werror(W_INTEGRAL2PTR_NOCAST);
2004 // shouldn't do that with float, array or structure unless to void
2005 if (!IS_VOID(getSpec(type)) &&
2006 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2007 werror(E_INCOMPAT_TYPES);
2011 } else { // from a pointer to a pointer
2012 if (IS_GENPTR(type) && IS_VOID(type->next))
2013 { // cast to void* is always allowed
2015 else if (IS_GENPTR(optype) && IS_VOID(optype->next))
2016 { // cast from void* is always allowed
2018 else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
2019 // if not a pointer to a function
2020 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2021 if (implicit) { // if not to generic, they have to match
2022 if (!IS_GENPTR(type) &&
2023 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
2024 ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
2028 werror(E_INCOMPAT_PTYPES);
2035 } else { // to a non pointer
2036 if (IS_PTR(optype)) { // from a pointer
2037 if (implicit) { // sneaky
2038 if (IS_INTEGRAL(type)) {
2039 werror(W_PTR2INTEGRAL_NOCAST);
2041 } else { // shouldn't do that with float, array or structure
2042 werror(E_INCOMPAT_TYPES);
2049 printFromToType (optype, type);
2052 /* if they are the same size create an assignment */
2054 /* This seems very dangerous to me, since there are several */
2055 /* optimizations (for example, gcse) that don't notice the */
2056 /* cast hidden in this assignement and may simplify an */
2057 /* iCode to use the original (uncasted) operand. */
2058 /* Unfortunately, other things break when this cast is */
2059 /* made explicit. Need to fix this someday. */
2060 /* -- EEP, 2004/01/21 */
2061 if (getSize (type) == getSize (optype) &&
2062 !IS_BITFIELD (type) &&
2064 !IS_FLOAT (optype) &&
2066 !IS_FIXED (optype) &&
2067 ((IS_SPEC (type) && IS_SPEC (optype)) ||
2068 (!IS_SPEC (type) && !IS_SPEC (optype))))
2070 ic = newiCode ('=', NULL, op);
2071 IC_RESULT (ic) = newiTempOperand (type, 0);
2072 SPIL_LOC (IC_RESULT (ic)) =
2073 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
2074 IC_RESULT (ic)->isaddr = 0;
2078 ic = newiCode (CAST, operandFromLink (type),
2079 geniCodeRValue (op, FALSE));
2081 IC_RESULT (ic) = newiTempOperand (type, 0);
2084 /* preserve the storage class & output class */
2085 /* of the original variable */
2086 restype = getSpec (operandType (IC_RESULT (ic)));
2087 if (!IS_LITERAL(opetype) &&
2090 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2091 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2094 return IC_RESULT (ic);
2097 /*-----------------------------------------------------------------*/
2098 /* geniCodeLabel - will create a Label */
2099 /*-----------------------------------------------------------------*/
2101 geniCodeLabel (symbol * label)
2105 ic = newiCodeLabelGoto (LABEL, label);
2109 /*-----------------------------------------------------------------*/
2110 /* geniCodeGoto - will create a Goto */
2111 /*-----------------------------------------------------------------*/
2113 geniCodeGoto (symbol * label)
2117 ic = newiCodeLabelGoto (GOTO, label);
2121 /*-----------------------------------------------------------------*/
2122 /* geniCodeMultiply - gen intermediate code for multiplication */
2123 /*-----------------------------------------------------------------*/
2125 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2132 /* if they are both literal then we know the result */
2133 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2134 return operandFromValue (valMult (left->operand.valOperand,
2135 right->operand.valOperand));
2137 if (IS_LITERAL(retype)) {
2138 p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2141 resType = usualBinaryConversions (&left, &right, resultType, '*');
2143 rtype = operandType (right);
2144 retype = getSpec (rtype);
2145 ltype = operandType (left);
2146 letype = getSpec (ltype);
2149 /* if the right is a literal & power of 2 */
2150 /* then make it a left shift */
2151 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2152 efficient in most cases than 2 bytes result = 2 bytes << literal
2153 if port has 1 byte muldiv */
2154 if (p2 && !IS_FLOAT (letype) && !IS_FIXED (letype)
2155 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2156 && (port->support.muldiv == 1))
2157 && strcmp (port->target, "pic16") != 0 /* don't shift for pic */
2158 && strcmp (port->target, "pic14") != 0)
2160 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2162 /* LEFT_OP need same size for left and result, */
2163 left = geniCodeCast (resType, left, TRUE);
2164 ltype = operandType (left);
2166 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2170 ic = newiCode ('*', left, right); /* normal multiplication */
2171 /* if the size left or right > 1 then support routine */
2172 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2176 IC_RESULT (ic) = newiTempOperand (resType, 1);
2179 return IC_RESULT (ic);
2182 /*-----------------------------------------------------------------*/
2183 /* geniCodeDivision - gen intermediate code for division */
2184 /*-----------------------------------------------------------------*/
2186 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2191 sym_link *rtype = operandType (right);
2192 sym_link *retype = getSpec (rtype);
2193 sym_link *ltype = operandType (left);
2194 sym_link *letype = getSpec (ltype);
2196 resType = usualBinaryConversions (&left, &right, resultType, '/');
2198 /* if the right is a literal & power of 2
2199 and left is unsigned then make it a
2201 if (IS_LITERAL (retype) &&
2202 !IS_FLOAT (letype) &&
2203 !IS_FIXED (letype) &&
2204 IS_UNSIGNED(letype) &&
2205 (p2 = powof2 ((TYPE_UDWORD)
2206 floatFromVal (right->operand.valOperand)))) {
2207 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2211 ic = newiCode ('/', left, right); /* normal division */
2212 /* if the size left or right > 1 then support routine */
2213 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2216 IC_RESULT (ic) = newiTempOperand (resType, 0);
2219 return IC_RESULT (ic);
2221 /*-----------------------------------------------------------------*/
2222 /* geniCodeModulus - gen intermediate code for modulus */
2223 /*-----------------------------------------------------------------*/
2225 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2231 /* if they are both literal then we know the result */
2232 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2233 return operandFromValue (valMod (left->operand.valOperand,
2234 right->operand.valOperand));
2236 resType = usualBinaryConversions (&left, &right, resultType, '%');
2238 /* now they are the same size */
2239 ic = newiCode ('%', left, right);
2241 /* if the size left or right > 1 then support routine */
2242 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2244 IC_RESULT (ic) = newiTempOperand (resType, 0);
2247 return IC_RESULT (ic);
2250 /*-----------------------------------------------------------------*/
2251 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2252 /*-----------------------------------------------------------------*/
2254 geniCodePtrPtrSubtract (operand * left, operand * right)
2260 /* if they are both literals then */
2261 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2263 result = operandFromValue (valMinus (left->operand.valOperand,
2264 right->operand.valOperand));
2268 ic = newiCode ('-', left, right);
2270 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2274 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2278 // should we really do this? is this ANSI?
2279 return geniCodeDivision (result,
2280 operandFromLit (getSize (ltype->next)),
2284 /*-----------------------------------------------------------------*/
2285 /* geniCodeSubtract - generates code for subtraction */
2286 /*-----------------------------------------------------------------*/
2288 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2295 /* if they both pointers then */
2296 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2297 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2298 return geniCodePtrPtrSubtract (left, right);
2300 /* if they are both literal then we know the result */
2301 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2302 && left->isLiteral && right->isLiteral)
2303 return operandFromValue (valMinus (left->operand.valOperand,
2304 right->operand.valOperand));
2306 /* if left is an array or pointer */
2307 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2309 isarray = left->isaddr;
2310 right = geniCodeMultiply (right,
2311 operandFromLit (getSize (ltype->next)),
2312 (getArraySizePtr(left) >= INTSIZE) ?
2315 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2318 { /* make them the same size */
2319 resType = usualBinaryConversions (&left, &right, resultType, '-');
2322 ic = newiCode ('-', left, right);
2324 IC_RESULT (ic) = newiTempOperand (resType, 1);
2325 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2327 /* if left or right is a float */
2328 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2329 || IS_FIXED (ltype) || IS_FIXED (rtype))
2333 return IC_RESULT (ic);
2336 /*-----------------------------------------------------------------*/
2337 /* geniCodeAdd - generates iCode for addition */
2338 /*-----------------------------------------------------------------*/
2340 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2349 /* if the right side is LITERAL zero */
2350 /* return the left side */
2351 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2354 /* if left is literal zero return right */
2355 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2358 /* if left is a pointer then size */
2359 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2361 isarray = left->isaddr;
2362 // there is no need to multiply with 1
2363 if (getSize (ltype->next) != 1)
2365 size = operandFromLit (getSize (ltype->next));
2366 SPEC_USIGN (getSpec (operandType (size))) = 1;
2367 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2368 right = geniCodeMultiply (right,
2370 (getArraySizePtr(left) >= INTSIZE) ?
2373 /* Even if right is a 'unsigned char',
2374 the result will be a 'signed int' due to the promotion rules.
2375 It doesn't make sense when accessing arrays, so let's fix it here: */
2377 SPEC_USIGN (getSpec (operandType (right))) = 1;
2379 resType = copyLinkChain (ltype);
2382 { // make them the same size
2383 resType = usualBinaryConversions (&left, &right, resultType, '+');
2386 /* if they are both literals then we know */
2387 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2388 && left->isLiteral && right->isLiteral)
2389 return operandFromValue (valPlus (valFromType (ltype),
2390 valFromType (rtype)));
2392 ic = newiCode ('+', left, right);
2394 IC_RESULT (ic) = newiTempOperand (resType, 1);
2395 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2397 /* if left or right is a float then support
2399 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2400 || IS_FIXED (ltype) || IS_FIXED (rtype))
2405 return IC_RESULT (ic);
2409 /*-----------------------------------------------------------------*/
2410 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2411 /*-----------------------------------------------------------------*/
2413 aggrToPtr (sym_link * type, bool force)
2418 if (IS_PTR (type) && !force)
2421 etype = getSpec (type);
2422 ptype = newLink (DECLARATOR);
2426 /* set the pointer depending on the storage class */
2427 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2431 /*------------------------------------------------------------------*/
2432 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2433 /*------------------------------------------------------------------*/
2435 aggrToPtrDclType (sym_link * type, bool force)
2437 if (IS_PTR (type) && !force)
2438 return DCL_TYPE (type);
2440 /* return the pointer depending on the storage class */
2441 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2444 /*-----------------------------------------------------------------*/
2445 /* geniCodeArray2Ptr - array to pointer */
2446 /*-----------------------------------------------------------------*/
2448 geniCodeArray2Ptr (operand * op)
2450 sym_link *optype = operandType (op);
2451 sym_link *opetype = getSpec (optype);
2453 /* set the pointer depending on the storage class */
2454 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2461 /*-----------------------------------------------------------------*/
2462 /* geniCodeArray - array access */
2463 /*-----------------------------------------------------------------*/
2465 geniCodeArray (operand * left, operand * right, int lvl)
2469 sym_link *ltype = operandType (left);
2474 if (IS_PTR (ltype->next) && left->isaddr)
2476 left = geniCodeRValue (left, FALSE);
2479 return geniCodeDerefPtr (geniCodeAdd (left,
2481 (getArraySizePtr(left) >= INTSIZE) ?
2487 size = operandFromLit (getSize (ltype->next));
2488 SPEC_USIGN (getSpec (operandType (size))) = 1;
2489 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2490 right = geniCodeMultiply (right,
2492 (getArraySizePtr(left) >= INTSIZE) ?
2495 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2496 It doesn't make sense when accessing arrays, so let's fix it here: */
2498 SPEC_USIGN (getSpec (operandType (right))) = 1;
2499 /* we can check for limits here */
2500 /* already done in SDCCast.c
2501 if (isOperandLiteral (right) &&
2504 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2506 werror (W_IDX_OUT_OF_BOUNDS,
2507 (int) operandLitValue (right) / getSize (ltype->next),
2512 ic = newiCode ('+', left, right);
2514 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2515 !IS_AGGREGATE (ltype->next) &&
2516 !IS_PTR (ltype->next))
2517 ? ltype : ltype->next), 0);
2519 if (!IS_AGGREGATE (ltype->next))
2521 IC_RESULT (ic)->isaddr = 1;
2522 IC_RESULT (ic)->aggr2ptr = 1;
2526 return IC_RESULT (ic);
2529 /*-----------------------------------------------------------------*/
2530 /* geniCodeStruct - generates intermediate code for structures */
2531 /*-----------------------------------------------------------------*/
2533 geniCodeStruct (operand * left, operand * right, bool islval)
2536 sym_link *type = operandType (left);
2537 sym_link *etype = getSpec (type);
2539 symbol *element = getStructElement (SPEC_STRUCT (etype),
2540 right->operand.symOperand);
2542 wassert(IS_SYMOP(right));
2544 /* add the offset */
2545 ic = newiCode ('+', left, operandFromLit (element->offset));
2547 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2549 /* preserve the storage & output class of the struct */
2550 /* as well as the volatile attribute */
2551 retype = getSpec (operandType (IC_RESULT (ic)));
2552 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2553 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2554 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2555 SPEC_CONST (retype) |= SPEC_CONST (etype);
2557 if (IS_PTR (element->type))
2558 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2560 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2563 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2566 /*-----------------------------------------------------------------*/
2567 /* geniCodePostInc - generate int code for Post increment */
2568 /*-----------------------------------------------------------------*/
2570 geniCodePostInc (operand * op)
2574 sym_link *optype = operandType (op);
2576 operand *rv = (IS_ITEMP (op) ?
2577 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2579 sym_link *rvtype = operandType (rv);
2582 /* if this is not an address we have trouble */
2585 werror (E_LVALUE_REQUIRED, "++");
2589 rOp = newiTempOperand (rvtype, 0);
2590 OP_SYMBOL(rOp)->noSpilLoc = 1;
2593 OP_SYMBOL(rv)->noSpilLoc = 1;
2595 geniCodeAssign (rOp, rv, 0, 0);
2597 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2599 werror(W_SIZEOF_VOID);
2600 if (IS_FLOAT (rvtype))
2601 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2603 if (IS_FIXED16X16 (rvtype))
2604 ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2606 ic = newiCode ('+', rv, operandFromLit (size));
2608 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2611 geniCodeAssign (op, result, 0, 0);
2617 /*-----------------------------------------------------------------*/
2618 /* geniCodePreInc - generate code for preIncrement */
2619 /*-----------------------------------------------------------------*/
2621 geniCodePreInc (operand * op, bool lvalue)
2624 sym_link *optype = operandType (op);
2625 operand *rop = (IS_ITEMP (op) ?
2626 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2628 sym_link *roptype = operandType (rop);
2634 werror (E_LVALUE_REQUIRED, "++");
2638 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2640 werror(W_SIZEOF_VOID);
2641 if (IS_FLOAT (roptype))
2642 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2644 if (IS_FIXED16X16 (roptype))
2645 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2647 ic = newiCode ('+', rop, operandFromLit (size));
2648 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2651 (void) geniCodeAssign (op, result, 0, 0);
2652 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2658 /*-----------------------------------------------------------------*/
2659 /* geniCodePostDec - generates code for Post decrement */
2660 /*-----------------------------------------------------------------*/
2662 geniCodePostDec (operand * op)
2666 sym_link *optype = operandType (op);
2668 operand *rv = (IS_ITEMP (op) ?
2669 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2671 sym_link *rvtype = operandType (rv);
2674 /* if this is not an address we have trouble */
2677 werror (E_LVALUE_REQUIRED, "--");
2681 rOp = newiTempOperand (rvtype, 0);
2682 OP_SYMBOL(rOp)->noSpilLoc = 1;
2685 OP_SYMBOL(rv)->noSpilLoc = 1;
2687 geniCodeAssign (rOp, rv, 0, 0);
2689 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2691 werror(W_SIZEOF_VOID);
2692 if (IS_FLOAT (rvtype))
2693 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2695 if (IS_FIXED16X16 (rvtype))
2696 ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2698 ic = newiCode ('-', rv, operandFromLit (size));
2700 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2703 geniCodeAssign (op, result, 0, 0);
2709 /*-----------------------------------------------------------------*/
2710 /* geniCodePreDec - generate code for pre decrement */
2711 /*-----------------------------------------------------------------*/
2713 geniCodePreDec (operand * op, bool lvalue)
2716 sym_link *optype = operandType (op);
2717 operand *rop = (IS_ITEMP (op) ?
2718 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2720 sym_link *roptype = operandType (rop);
2726 werror (E_LVALUE_REQUIRED, "--");
2730 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2732 werror(W_SIZEOF_VOID);
2733 if (IS_FLOAT (roptype))
2734 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2736 if (IS_FIXED16X16 (roptype))
2737 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2739 ic = newiCode ('-', rop, operandFromLit (size));
2740 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2743 (void) geniCodeAssign (op, result, 0, 0);
2744 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2751 /*-----------------------------------------------------------------*/
2752 /* geniCodeBitwise - gen int code for bitWise operators */
2753 /*-----------------------------------------------------------------*/
2755 geniCodeBitwise (operand * left, operand * right,
2756 int oper, sym_link * resType)
2760 left = geniCodeCast (resType, left, TRUE);
2761 right = geniCodeCast (resType, right, TRUE);
2763 ic = newiCode (oper, left, right);
2764 IC_RESULT (ic) = newiTempOperand (resType, 0);
2767 return IC_RESULT (ic);
2770 /*-----------------------------------------------------------------*/
2771 /* geniCodeAddressOf - gens icode for '&' address of operator */
2772 /*-----------------------------------------------------------------*/
2774 geniCodeAddressOf (operand * op)
2778 sym_link *optype = operandType (op);
2779 sym_link *opetype = getSpec (optype);
2781 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2783 op = operandFromOperand (op);
2788 /* lvalue check already done in decorateType */
2789 /* this must be a lvalue */
2790 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2791 /* werror (E_LVALUE_REQUIRED,"&"); */
2795 p = newLink (DECLARATOR);
2797 /* set the pointer depending on the storage class */
2798 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2800 p->next = copyLinkChain (optype);
2802 /* if already a temp */
2805 setOperandType (op, p);
2810 /* other wise make this of the type coming in */
2811 ic = newiCode (ADDRESS_OF, op, NULL);
2812 IC_RESULT (ic) = newiTempOperand (p, 1);
2813 IC_RESULT (ic)->isaddr = 0;
2815 return IC_RESULT (ic);
2817 /*-----------------------------------------------------------------*/
2818 /* setOClass - sets the output class depending on the pointer type */
2819 /*-----------------------------------------------------------------*/
2821 setOClass (sym_link * ptr, sym_link * spec)
2823 switch (DCL_TYPE (ptr))
2826 SPEC_OCLS (spec) = data;
2830 SPEC_OCLS (spec) = generic;
2834 SPEC_OCLS (spec) = xdata;
2838 SPEC_OCLS (spec) = code;
2842 SPEC_OCLS (spec) = idata;
2846 SPEC_OCLS (spec) = xstack;
2850 SPEC_OCLS (spec) = eeprom;
2859 /*-----------------------------------------------------------------*/
2860 /* geniCodeDerefPtr - dereference pointer with '*' */
2861 /*-----------------------------------------------------------------*/
2863 geniCodeDerefPtr (operand * op,int lvl)
2865 sym_link *rtype, *retype;
2866 sym_link *optype = operandType (op);
2868 // if this is an array then array access
2869 if (IS_ARRAY (optype)) {
2870 // don't worry, this will be optimized out later
2871 return geniCodeArray (op, operandFromLit (0), lvl);
2874 // just in case someone screws up
2875 wassert (IS_PTR (optype));
2877 if (IS_TRUE_SYMOP (op))
2880 op = geniCodeRValue (op, TRUE);
2883 /* now get rid of the pointer part */
2884 if (isLvaluereq(lvl) && IS_ITEMP (op))
2886 retype = getSpec (rtype = copyLinkChain (optype));
2890 retype = getSpec (rtype = copyLinkChain (optype->next));
2891 /* outputclass needs 2b updated */
2892 setOClass (optype, retype);
2895 op->isGptr = IS_GENPTR (optype);
2897 op->isaddr = (IS_PTR (rtype) ||
2898 IS_STRUCT (rtype) ||
2904 if (!isLvaluereq(lvl))
2905 op = geniCodeRValue (op, TRUE);
2907 setOperandType (op, rtype);
2912 /*-----------------------------------------------------------------*/
2913 /* geniCodeUnaryMinus - does a unary minus of the operand */
2914 /*-----------------------------------------------------------------*/
2916 geniCodeUnaryMinus (operand * op)
2919 sym_link *optype = operandType (op);
2921 if (IS_LITERAL (optype))
2922 return operandFromLit (-floatFromVal (op->operand.valOperand));
2924 ic = newiCode (UNARYMINUS, op, NULL);
2925 IC_RESULT (ic) = newiTempOperand (optype, 0);
2927 return IC_RESULT (ic);
2930 /*-----------------------------------------------------------------*/
2931 /* geniCodeLeftShift - gen i code for left shift */
2932 /*-----------------------------------------------------------------*/
2934 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2939 ic = newiCode (LEFT_OP, left, right);
2941 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2942 IC_RESULT (ic) = newiTempOperand (resType, 0);
2944 return IC_RESULT (ic);
2947 /*-----------------------------------------------------------------*/
2948 /* geniCodeRightShift - gen i code for right shift */
2949 /*-----------------------------------------------------------------*/
2951 geniCodeRightShift (operand * left, operand * right)
2955 ic = newiCode (RIGHT_OP, left, right);
2956 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2958 return IC_RESULT (ic);
2961 /*-----------------------------------------------------------------*/
2962 /* geniCodeLogic- logic code */
2963 /*-----------------------------------------------------------------*/
2965 geniCodeLogic (operand * left, operand * right, int op)
2969 sym_link *rtype = operandType (right);
2970 sym_link *ltype = operandType (left);
2972 /* left is integral type and right is literal then
2973 check if the literal value is within bounds */
2974 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2976 checkConstantRange(ltype,
2977 OP_VALUE(right), "compare operation", 1);
2980 /* if one operand is a pointer and the other is a literal generic void pointer,
2981 change the type of the literal generic void pointer to match the other pointer */
2982 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2983 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2985 /* find left's definition */
2986 ic = (iCode *) setFirstItem (iCodeChain);
2989 if (((ic->op == CAST) || (ic->op == '='))
2990 && isOperandEqual(left, IC_RESULT (ic)))
2993 ic = setNextItem (iCodeChain);
2995 /* if casting literal to generic pointer, then cast to rtype instead */
2996 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2998 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2999 ltype = operandType(left);
3002 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
3003 && IS_PTR (ltype) && !IS_GENPTR(ltype))
3005 /* find right's definition */
3006 ic = (iCode *) setFirstItem (iCodeChain);
3009 if (((ic->op == CAST) || (ic->op == '='))
3010 && isOperandEqual(right, IC_RESULT (ic)))
3013 ic = setNextItem (iCodeChain);
3015 /* if casting literal to generic pointer, then cast to rtype instead */
3016 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
3018 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
3019 rtype = operandType(right);
3023 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
3025 ic = newiCode (op, left, right);
3026 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
3028 /* if comparing float
3029 and not a '==' || '!=' || '&&' || '||' (these
3031 if (IS_FLOAT(ctype) &&
3038 /* if comparing a fixed type use support functions */
3039 if (IS_FIXED(ctype))
3043 return IC_RESULT (ic);
3046 /*-----------------------------------------------------------------*/
3047 /* geniCodeLogicAndOr - && || operations */
3048 /*-----------------------------------------------------------------*/
3050 geniCodeLogicAndOr (ast *tree, int lvl)
3053 symbol *falseLabel = newiTempLabel (NULL);
3054 symbol *trueLabel = newiTempLabel (NULL);
3055 symbol *exitLabel = newiTempLabel (NULL);
3056 operand *op, *result, *condition;
3058 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3059 They can be reenabled by executing the following block. If you find
3060 a decent optimization you could start right here:
3065 operand *leftOp, *rightOp;
3067 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3068 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3070 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3074 /* generate two IFX for the '&&' or '||' op */
3076 /* evaluate left operand */
3077 condition = ast2iCode (tree->left, lvl + 1);
3078 op = geniCodeRValue (condition, FALSE);
3080 /* test left operand */
3081 if (tree->opval.op == AND_OP)
3082 ic = newiCodeCondition (op, NULL, falseLabel);
3084 ic = newiCodeCondition (op, trueLabel, NULL);
3087 /* evaluate right operand */
3088 condition = ast2iCode (tree->right, lvl + 1);
3089 op = geniCodeRValue (condition, FALSE);
3091 /* test right operand */
3092 ic = newiCodeCondition (op, trueLabel, NULL);
3095 /* store 0 or 1 in result */
3096 result = newiTempOperand (newCharLink(), 1);
3098 geniCodeLabel (falseLabel);
3099 geniCodeAssign (result, operandFromLit (0), 0, 0);
3100 /* generate an unconditional goto */
3101 geniCodeGoto (exitLabel);
3103 geniCodeLabel (trueLabel);
3104 geniCodeAssign (result, operandFromLit (1), 0, 0);
3106 geniCodeLabel (exitLabel);
3111 /*-----------------------------------------------------------------*/
3112 /* geniCodeUnary - for a a generic unary operation */
3113 /*-----------------------------------------------------------------*/
3115 geniCodeUnary (operand * op, int oper)
3117 iCode *ic = newiCode (oper, op, NULL);
3119 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3121 return IC_RESULT (ic);
3124 /*-----------------------------------------------------------------*/
3125 /* geniCodeConditional - geniCode for '?' ':' operation */
3126 /*-----------------------------------------------------------------*/
3128 geniCodeConditional (ast * tree,int lvl)
3131 symbol *falseLabel = newiTempLabel (NULL);
3132 symbol *exitLabel = newiTempLabel (NULL);
3133 operand *cond = ast2iCode (tree->left,lvl+1);
3134 operand *true, *false, *result;
3136 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3140 true = ast2iCode (tree->right->left,lvl+1);
3142 /* move the value to a new Operand */
3143 result = newiTempOperand (tree->right->ftype, 0);
3144 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3146 /* generate an unconditional goto */
3147 geniCodeGoto (exitLabel);
3149 /* now for the right side */
3150 geniCodeLabel (falseLabel);
3152 false = ast2iCode (tree->right->right,lvl+1);
3153 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3155 /* create the exit label */
3156 geniCodeLabel (exitLabel);
3161 /*-----------------------------------------------------------------*/
3162 /* geniCodeAssign - generate code for assignment */
3163 /*-----------------------------------------------------------------*/
3165 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3168 sym_link *ltype = operandType (left);
3169 sym_link *rtype = operandType (right);
3171 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3173 werror (E_LVALUE_REQUIRED, "assignment");
3177 /* left is integral type and right is literal then
3178 check if the literal value is within bounds */
3179 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3181 checkConstantRange(ltype,
3182 OP_VALUE(right), "= operation", 0);
3185 /* if the left & right type don't exactly match */
3186 /* if pointer set then make sure the check is
3187 done with the type & not the pointer */
3188 /* then cast rights type to left */
3190 /* first check the type for pointer assignement */
3191 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3192 compareType (ltype, rtype) <= 0)
3194 if (compareType (ltype->next, rtype) < 0)
3195 right = geniCodeCast (ltype->next, right, TRUE);
3197 else if (compareType (ltype, rtype) < 0)
3198 right = geniCodeCast (ltype, right, TRUE);
3200 /* If left is a true symbol & ! volatile
3201 create an assignment to temporary for
3202 the right & then assign this temporary
3203 to the symbol. This is SSA (static single
3204 assignment). Isn't it simple and folks have
3205 published mountains of paper on it */
3206 if (IS_TRUE_SYMOP (left) &&
3207 !isOperandVolatile (left, FALSE) &&
3208 isOperandGlobal (left))
3212 if (IS_TRUE_SYMOP (right))
3213 sym = OP_SYMBOL (right);
3214 ic = newiCode ('=', NULL, right);
3215 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3216 SPIL_LOC (right) = sym;
3220 ic = newiCode ('=', NULL, right);
3221 IC_RESULT (ic) = left;
3224 /* if left isgptr flag is set then support
3225 routine will be required */
3229 ic->nosupdate = nosupdate;
3233 /*-----------------------------------------------------------------*/
3234 /* geniCodeDummyRead - generate code for dummy read */
3235 /*-----------------------------------------------------------------*/
3237 geniCodeDummyRead (operand * op)
3240 sym_link *type = operandType (op);
3242 if (!IS_VOLATILE(type))
3245 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3251 /*-----------------------------------------------------------------*/
3252 /* geniCodeSEParms - generate code for side effecting fcalls */
3253 /*-----------------------------------------------------------------*/
3255 geniCodeSEParms (ast * parms,int lvl)
3260 if (parms->type == EX_OP && parms->opval.op == PARAM)
3262 geniCodeSEParms (parms->left,lvl);
3263 geniCodeSEParms (parms->right,lvl);
3267 /* hack don't like this but too lazy to think of
3269 if (IS_ADDRESS_OF_OP (parms))
3270 parms->left->lvalue = 1;
3272 if (IS_CAST_OP (parms) &&
3273 IS_PTR (parms->ftype) &&
3274 IS_ADDRESS_OF_OP (parms->right))
3275 parms->right->left->lvalue = 1;
3277 parms->opval.oprnd =
3278 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3280 parms->type = EX_OPERAND;
3281 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3282 SPEC_ARGREG(parms->ftype);
3285 /*-----------------------------------------------------------------*/
3286 /* geniCodeParms - generates parameters */
3287 /*-----------------------------------------------------------------*/
3289 geniCodeParms (ast * parms, value *argVals, int *stack,
3290 sym_link * ftype, int lvl)
3298 if (argVals==NULL) {
3300 argVals = FUNC_ARGS (ftype);
3303 /* if this is a param node then do the left & right */
3304 if (parms->type == EX_OP && parms->opval.op == PARAM)
3306 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3307 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3311 /* get the parameter value */
3312 if (parms->type == EX_OPERAND)
3313 pval = parms->opval.oprnd;
3316 /* maybe this else should go away ?? */
3317 /* hack don't like this but too lazy to think of
3319 if (IS_ADDRESS_OF_OP (parms))
3320 parms->left->lvalue = 1;
3322 if (IS_CAST_OP (parms) &&
3323 IS_PTR (parms->ftype) &&
3324 IS_ADDRESS_OF_OP (parms->right))
3325 parms->right->left->lvalue = 1;
3327 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3330 /* if register parm then make it a send */
3331 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3332 IFFUNC_ISBUILTIN(ftype))
3334 ic = newiCode (SEND, pval, NULL);
3335 ic->argreg = SPEC_ARGREG(parms->etype);
3336 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3341 /* now decide whether to push or assign */
3342 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3346 operand *top = operandFromSymbol (argVals->sym);
3347 /* clear useDef and other bitVectors */
3348 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3349 geniCodeAssign (top, pval, 1, 0);
3353 sym_link *p = operandType (pval);
3355 ic = newiCode (IPUSH, pval, NULL);
3357 /* update the stack adjustment */
3358 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3363 argVals=argVals->next;
3367 /*-----------------------------------------------------------------*/
3368 /* geniCodeCall - generates temp code for calling */
3369 /*-----------------------------------------------------------------*/
3371 geniCodeCall (operand * left, ast * parms,int lvl)
3375 sym_link *type, *etype;
3379 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3380 !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3381 werror (E_FUNCTION_EXPECTED);
3382 return operandFromValue(valueFromLit(0));
3385 /* take care of parameters with side-effecting
3386 function calls in them, this is required to take care
3387 of overlaying function parameters */
3388 geniCodeSEParms (parms,lvl);
3390 ftype = operandType (left);
3391 if (IS_FUNCPTR (ftype))
3392 ftype = ftype->next;
3394 /* first the parameters */
3395 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3397 /* now call : if symbol then pcall */
3398 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3399 ic = newiCode (PCALL, left, NULL);
3401 ic = newiCode (CALL, left, NULL);
3404 type = copyLinkChain (ftype->next);
3405 etype = getSpec (type);
3406 SPEC_EXTR (etype) = 0;
3407 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3411 /* stack adjustment after call */
3412 ic->parmBytes = stack;
3417 /*-----------------------------------------------------------------*/
3418 /* geniCodeReceive - generate intermediate code for "receive" */
3419 /*-----------------------------------------------------------------*/
3421 geniCodeReceive (value * args)
3423 unsigned char paramByteCounter = 0;
3425 /* for all arguments that are passed in registers */
3429 if (IS_REGPARM (args->etype))
3431 operand *opr = operandFromValue (args);
3433 symbol *sym = OP_SYMBOL (opr);
3436 /* we will use it after all optimizations
3437 and before liveRange calculation */
3438 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3441 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3442 options.stackAuto == 0 &&
3443 (!(options.model == MODEL_FLAT24)) )
3448 opl = newiTempOperand (args->type, 0);
3450 sym->reqv->key = sym->key;
3451 OP_SYMBOL (sym->reqv)->key = sym->key;
3452 OP_SYMBOL (sym->reqv)->isreqv = 1;
3453 OP_SYMBOL (sym->reqv)->islocal = 0;
3454 SPIL_LOC (sym->reqv) = sym;
3458 ic = newiCode (RECEIVE, NULL, NULL);
3459 ic->argreg = SPEC_ARGREG(args->etype);
3461 currFunc->recvSize = getSize (sym->type);
3464 IC_RESULT (ic) = opr;
3466 /* misuse of parmBytes (normally used for functions)
3467 * to save estimated stack position of this argument.
3468 * Normally this should be zero for RECEIVE iCodes.
3469 * No idea if this causes side effects on other ports. - dw
3471 ic->parmBytes = paramByteCounter;
3473 /* what stack position do we have? */
3474 paramByteCounter += getSize (sym->type);
3483 /*-----------------------------------------------------------------*/
3484 /* geniCodeFunctionBody - create the function body */
3485 /*-----------------------------------------------------------------*/
3487 geniCodeFunctionBody (ast * tree,int lvl)
3494 /* reset the auto generation */
3500 func = ast2iCode (tree->left,lvl+1);
3501 fetype = getSpec (operandType (func));
3503 savelineno = lineno;
3504 lineno = OP_SYMBOL (func)->lineDef;
3505 /* create an entry label */
3506 geniCodeLabel (entryLabel);
3507 lineno = savelineno;
3509 /* create a proc icode */
3510 ic = newiCode (FUNCTION, func, NULL);
3511 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3516 /* for all parameters that are passed
3517 on registers add a "receive" */
3518 geniCodeReceive (tree->values.args);
3520 /* generate code for the body */
3521 ast2iCode (tree->right,lvl+1);
3523 /* create a label for return */
3524 geniCodeLabel (returnLabel);
3526 /* now generate the end proc */
3527 ic = newiCode (ENDFUNCTION, func, NULL);
3533 /*-----------------------------------------------------------------*/
3534 /* geniCodeReturn - gen icode for 'return' statement */
3535 /*-----------------------------------------------------------------*/
3537 geniCodeReturn (operand * op)
3541 /* if the operand is present force an rvalue */
3543 op = geniCodeRValue (op, FALSE);
3545 ic = newiCode (RETURN, op, NULL);
3549 /*-----------------------------------------------------------------*/
3550 /* geniCodeIfx - generates code for extended if statement */
3551 /*-----------------------------------------------------------------*/
3553 geniCodeIfx (ast * tree,int lvl)
3556 operand *condition = ast2iCode (tree->left,lvl+1);
3559 /* if condition is null then exit */
3563 condition = geniCodeRValue (condition, FALSE);
3565 cetype = getSpec (operandType (condition));
3566 /* if the condition is a literal */
3567 if (IS_LITERAL (cetype))
3569 if (floatFromVal (condition->operand.valOperand))
3571 if (tree->trueLabel)
3572 geniCodeGoto (tree->trueLabel);
3578 if (tree->falseLabel)
3579 geniCodeGoto (tree->falseLabel);
3586 if (tree->trueLabel)
3588 ic = newiCodeCondition (condition,
3593 if (tree->falseLabel)
3594 geniCodeGoto (tree->falseLabel);
3598 ic = newiCodeCondition (condition,
3605 ast2iCode (tree->right,lvl+1);
3608 /*-----------------------------------------------------------------*/
3609 /* geniCodeJumpTable - tries to create a jump table for switch */
3610 /*-----------------------------------------------------------------*/
3612 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3614 int min, max, cnt = 1;
3621 int needRangeCheck = !optimize.noJTabBoundary
3622 || tree->values.switchVals.swDefault;
3623 sym_link *cetype = getSpec (operandType (cond));
3624 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3625 int sizeofMatchJump, sizeofJumpTable;
3628 if (!tree || !caseVals)
3631 /* the criteria for creating a jump table is */
3632 /* all integer numbers between the maximum & minimum must */
3633 /* be present , the maximum value should not exceed 255 */
3634 /* If not all integer numbers are present the algorithm */
3635 /* inserts jumps to the default label for the missing numbers */
3636 /* and decides later whether it is worth it */
3637 min = (int) floatFromVal (vch = caseVals);
3644 max = (int) floatFromVal (vch);
3646 /* Exit if the range is too large to handle with a jump table. */
3647 if (1 + max - min > port->jumptableCost.maxCount)
3650 switch (getSize (operandType (cond)))
3652 case 1: sizeIndex = 0; break;
3653 case 2: sizeIndex = 1; break;
3654 case 4: sizeIndex = 2; break;
3658 /* Compute the size cost of the range check and subtraction. */
3660 sizeofZeroMinCost = 0;
3664 if (!(min==0 && IS_UNSIGNED (cetype)))
3665 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3666 if (!IS_UNSIGNED (cetype))
3667 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3668 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3671 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3673 /* If the size cost of handling a non-zero minimum exceeds the */
3674 /* cost of extending the range down to zero, then it might be */
3675 /* better to extend the range to zero. */
3676 if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3677 >= (min * port->jumptableCost.sizeofElement))
3679 /* Only extend the jump table if it would still be manageable. */
3680 if (1 + max <= port->jumptableCost.maxCount)
3683 if (IS_UNSIGNED (cetype))
3686 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3690 /* Compute the total size cost of a jump table. */
3691 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3692 + port->jumptableCost.sizeofDispatch
3693 + sizeofMinCost + sizeofMaxCost;
3695 /* Compute the total size cost of a match & jump sequence */
3696 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3698 /* If the size cost of the jump table is uneconomical then exit */
3699 if (sizeofMatchJump < sizeofJumpTable)
3702 /* The jump table is preferable. */
3704 /* First, a label for the default or missing cases. */
3705 if (tree->values.switchVals.swDefault)
3707 SNPRINTF (buffer, sizeof(buffer),
3709 tree->values.switchVals.swNum);
3713 SNPRINTF (buffer, sizeof(buffer),
3715 tree->values.switchVals.swNum);
3717 falseLabel = newiTempLabel (buffer);
3719 /* Build the list of labels for the jump table. */
3721 t = (int) floatFromVal (vch);
3722 for (i=min; i<=max; i++)
3726 /* Explicit case: make a new label for it. */
3727 SNPRINTF (buffer, sizeof(buffer),
3729 tree->values.switchVals.swNum,
3731 addSet (&labels, newiTempLabel (buffer));
3734 t = (int) floatFromVal (vch);
3738 /* Implicit case: use the default label. */
3739 addSet (&labels, falseLabel);
3743 /* first we rule out the boundary conditions */
3744 /* if only optimization says so */
3747 sym_link *cetype = getSpec (operandType (cond));
3748 /* no need to check the lower bound if
3749 the condition is unsigned & minimum value is zero */
3750 if (!(min == 0 && IS_UNSIGNED (cetype)))
3752 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3753 ic = newiCodeCondition (boundary, falseLabel, NULL);
3757 /* now for upper bounds */
3758 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3759 ic = newiCodeCondition (boundary, falseLabel, NULL);
3763 /* if the min is not zero then we no make it zero */
3766 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3767 if (!IS_LITERAL(getSpec(operandType(cond))))
3768 setOperandType (cond, UCHARTYPE);
3771 /* now create the jumptable */
3772 ic = newiCode (JUMPTABLE, NULL, NULL);
3773 IC_JTCOND (ic) = cond;
3774 IC_JTLABELS (ic) = labels;
3779 /*-----------------------------------------------------------------*/
3780 /* geniCodeSwitch - changes a switch to a if statement */
3781 /*-----------------------------------------------------------------*/
3783 geniCodeSwitch (ast * tree,int lvl)
3786 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3787 value *caseVals = tree->values.switchVals.swVals;
3788 symbol *trueLabel, *falseLabel;
3790 /* If the condition is a literal, then just jump to the */
3791 /* appropriate case label. */
3792 if (IS_LITERAL(getSpec(operandType(cond))))
3794 int switchVal, caseVal;
3796 switchVal = (int) floatFromVal (cond->operand.valOperand);
3799 caseVal = (int) floatFromVal (caseVals);
3800 if (caseVal == switchVal)
3802 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3803 tree->values.switchVals.swNum, caseVal);
3804 trueLabel = newiTempLabel (buffer);
3805 geniCodeGoto (trueLabel);
3808 caseVals = caseVals->next;
3810 goto defaultOrBreak;
3813 /* If cond is volatile, it might change while we are trying to */
3814 /* find the matching case. To avoid this possibility, make a */
3815 /* non-volatile copy to use instead. */
3816 if (IS_OP_VOLATILE (cond))
3821 newcond = newiTempOperand (operandType (cond), TRUE);
3822 newcond->isvolatile = 0;
3823 ic = newiCode ('=', NULL, cond);
3824 IC_RESULT (ic) = newcond;
3829 /* if we can make this a jump table */
3830 if (geniCodeJumpTable (cond, caseVals, tree))
3831 goto jumpTable; /* no need for the comparison */
3833 /* for the cases defined do */
3837 operand *compare = geniCodeLogic (cond,
3838 operandFromValue (caseVals),
3841 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3842 tree->values.switchVals.swNum,
3843 (int) floatFromVal (caseVals));
3844 trueLabel = newiTempLabel (buffer);
3846 ic = newiCodeCondition (compare, trueLabel, NULL);
3848 caseVals = caseVals->next;
3853 /* if default is present then goto break else break */
3854 if (tree->values.switchVals.swDefault)
3856 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3860 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3863 falseLabel = newiTempLabel (buffer);
3864 geniCodeGoto (falseLabel);
3867 ast2iCode (tree->right,lvl+1);
3870 /*-----------------------------------------------------------------*/
3871 /* geniCodeInline - intermediate code for inline assembler */
3872 /*-----------------------------------------------------------------*/
3874 geniCodeInline (ast * tree)
3878 ic = newiCode (INLINEASM, NULL, NULL);
3879 IC_INLINE (ic) = tree->values.inlineasm;
3883 /*-----------------------------------------------------------------*/
3884 /* geniCodeArrayInit - intermediate code for array initializer */
3885 /*-----------------------------------------------------------------*/
3887 geniCodeArrayInit (ast * tree, operand *array)
3891 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3892 ic = newiCode (ARRAYINIT, array, NULL);
3893 IC_ARRAYILIST (ic) = tree->values.constlist;
3895 operand *left=newOperand(), *right=newOperand();
3896 left->type=right->type=SYMBOL;
3897 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3898 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3899 ic = newiCode (ARRAYINIT, left, right);
3904 /*-----------------------------------------------------------------*/
3905 /* geniCodeCritical - intermediate code for a critical statement */
3906 /*-----------------------------------------------------------------*/
3908 geniCodeCritical (ast *tree, int lvl)
3914 if (!options.stackAuto)
3916 type = newLink(SPECIFIER);
3917 SPEC_VOLATILE(type) = 1;
3918 SPEC_NOUN(type) = V_BIT;
3919 SPEC_SCLS(type) = S_BIT;
3920 SPEC_BLEN(type) = 1;
3921 SPEC_BSTR(type) = 0;
3922 op = newiTempOperand(type, 1);
3925 /* If op is NULL, the original interrupt state will saved on */
3926 /* the stack. Otherwise, it will be saved in op. */
3928 /* Generate a save of the current interrupt state & disable */
3929 ic = newiCode (CRITICAL, NULL, NULL);
3930 IC_RESULT (ic) = op;
3933 /* Generate the critical code sequence */
3934 if (tree->left && tree->left->type == EX_VALUE)
3935 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3937 ast2iCode (tree->left,lvl+1);
3939 /* Generate a restore of the original interrupt state */
3940 ic = newiCode (ENDCRITICAL, NULL, op);
3944 /*-----------------------------------------------------------------*/
3945 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3946 /* particular case. Ie : assigning or dereferencing array or ptr */
3947 /*-----------------------------------------------------------------*/
3948 set * lvaluereqSet = NULL;
3949 typedef struct lvalItem
3956 /*-----------------------------------------------------------------*/
3957 /* addLvaluereq - add a flag for lvalreq for current ast level */
3958 /*-----------------------------------------------------------------*/
3959 void addLvaluereq(int lvl)
3961 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3964 addSetHead(&lvaluereqSet,lpItem);
3967 /*-----------------------------------------------------------------*/
3968 /* delLvaluereq - del a flag for lvalreq for current ast level */
3969 /*-----------------------------------------------------------------*/
3973 lpItem = getSet(&lvaluereqSet);
3974 if(lpItem) Safe_free(lpItem);
3976 /*-----------------------------------------------------------------*/
3977 /* clearLvaluereq - clear lvalreq flag */
3978 /*-----------------------------------------------------------------*/
3979 void clearLvaluereq()
3982 lpItem = peekSet(lvaluereqSet);
3983 if(lpItem) lpItem->req = 0;
3985 /*-----------------------------------------------------------------*/
3986 /* getLvaluereq - get the last lvalreq level */
3987 /*-----------------------------------------------------------------*/
3988 int getLvaluereqLvl()
3991 lpItem = peekSet(lvaluereqSet);
3992 if(lpItem) return lpItem->lvl;
3995 /*-----------------------------------------------------------------*/
3996 /* isLvaluereq - is lvalreq valid for this level ? */
3997 /*-----------------------------------------------------------------*/
3998 int isLvaluereq(int lvl)
4001 lpItem = peekSet(lvaluereqSet);
4002 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
4006 /*-----------------------------------------------------------------*/
4007 /* ast2iCode - creates an icodeList from an ast */
4008 /*-----------------------------------------------------------------*/
4010 ast2iCode (ast * tree,int lvl)
4012 operand *left = NULL;
4013 operand *right = NULL;
4017 /* set the global variables for filename & line number */
4019 filename = tree->filename;
4021 lineno = tree->lineno;
4023 block = tree->block;
4025 scopeLevel = tree->level;
4027 seqPoint = tree->seqPoint;
4029 if (tree->type == EX_VALUE)
4030 return operandFromValue (tree->opval.val);
4032 if (tree->type == EX_LINK)
4033 return operandFromLink (tree->opval.lnk);
4035 /* if we find a nullop */
4036 if (tree->type == EX_OP &&
4037 (tree->opval.op == NULLOP ||
4038 tree->opval.op == BLOCK))
4040 if (tree->left && tree->left->type == EX_VALUE)
4041 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4043 ast2iCode (tree->left,lvl+1);
4044 if (tree->right && tree->right->type == EX_VALUE)
4045 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4047 ast2iCode (tree->right,lvl+1);
4051 /* special cases for not evaluating */
4052 if (tree->opval.op != ':' &&
4053 tree->opval.op != '?' &&
4054 tree->opval.op != CALL &&
4055 tree->opval.op != IFX &&
4056 tree->opval.op != AND_OP &&
4057 tree->opval.op != OR_OP &&
4058 tree->opval.op != LABEL &&
4059 tree->opval.op != GOTO &&
4060 tree->opval.op != SWITCH &&
4061 tree->opval.op != FUNCTION &&
4062 tree->opval.op != INLINEASM &&
4063 tree->opval.op != CRITICAL)
4066 if (IS_ASSIGN_OP (tree->opval.op) ||
4067 IS_DEREF_OP (tree) ||
4068 (tree->opval.op == '&' && !tree->right) ||
4069 tree->opval.op == PTR_OP)
4072 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4073 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4076 left = operandFromAst (tree->left,lvl);
4078 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4079 left = geniCodeRValue (left, TRUE);
4083 left = operandFromAst (tree->left,lvl);
4085 if (tree->opval.op == INC_OP ||
4086 tree->opval.op == DEC_OP)
4089 right = operandFromAst (tree->right,lvl);
4094 right = operandFromAst (tree->right,lvl);
4098 /* now depending on the type of operand */
4099 /* this will be a biggy */
4100 switch (tree->opval.op)
4103 case '[': /* array operation */
4105 //sym_link *ltype = operandType (left);
4106 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4107 left = geniCodeRValue (left, FALSE);
4108 right = geniCodeRValue (right, TRUE);
4111 return geniCodeArray (left, right,lvl);
4113 case '.': /* structure dereference */
4114 if (IS_PTR (operandType (left)))
4115 left = geniCodeRValue (left, TRUE);
4117 left = geniCodeRValue (left, FALSE);
4119 return geniCodeStruct (left, right, tree->lvalue);
4121 case PTR_OP: /* structure pointer dereference */
4124 pType = operandType (left);
4125 left = geniCodeRValue (left, TRUE);
4127 setOClass (pType, getSpec (operandType (left)));
4130 return geniCodeStruct (left, right, tree->lvalue);
4132 case INC_OP: /* increment operator */
4134 return geniCodePostInc (left);
4136 return geniCodePreInc (right, tree->lvalue);
4138 case DEC_OP: /* decrement operator */
4140 return geniCodePostDec (left);
4142 return geniCodePreDec (right, tree->lvalue);
4144 case '&': /* bitwise and or address of operator */
4146 { /* this is a bitwise operator */
4147 left = geniCodeRValue (left, FALSE);
4148 right = geniCodeRValue (right, FALSE);
4149 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4152 return geniCodeAddressOf (left);
4154 case '|': /* bitwise or & xor */
4156 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4157 geniCodeRValue (right, FALSE),
4162 return geniCodeDivision (geniCodeRValue (left, FALSE),
4163 geniCodeRValue (right, FALSE),
4164 getResultTypeFromType (tree->ftype));
4167 return geniCodeModulus (geniCodeRValue (left, FALSE),
4168 geniCodeRValue (right, FALSE),
4169 getResultTypeFromType (tree->ftype));
4172 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4173 geniCodeRValue (right, FALSE),
4174 getResultTypeFromType (tree->ftype));
4176 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4180 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4181 geniCodeRValue (right, FALSE),
4182 getResultTypeFromType (tree->ftype));
4184 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4188 return geniCodeAdd (geniCodeRValue (left, FALSE),
4189 geniCodeRValue (right, FALSE),
4190 getResultTypeFromType (tree->ftype),
4193 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4196 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4197 geniCodeRValue (right, FALSE),
4198 getResultTypeFromType (tree->ftype));
4201 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4202 geniCodeRValue (right, FALSE));
4204 #if 0 // this indeed needs a second thought
4208 // let's keep this simple: get the rvalue we need
4209 op=geniCodeRValue (right, FALSE);
4210 // now cast it to whatever we want
4211 op=geniCodeCast (operandType(left), op, FALSE);
4212 // if this is going to be used as an lvalue, make it so
4218 #else // bug #604575, is it a bug ????
4219 return geniCodeCast (operandType (left),
4220 geniCodeRValue (right, FALSE), FALSE);
4227 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4232 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4233 setOperandType (op, UCHARTYPE);
4238 return geniCodeLogicAndOr (tree, lvl);
4245 /* different compilers (even different gccs) evaluate
4246 the two calls in a different order. to get the same
4247 result on all machines we've to specify a clear sequence.
4248 return geniCodeLogic (geniCodeRValue (left, FALSE),
4249 geniCodeRValue (right, FALSE),
4253 operand *leftOp, *rightOp;
4255 leftOp = geniCodeRValue (left , FALSE);
4256 rightOp = geniCodeRValue (right, FALSE);
4258 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4261 return geniCodeConditional (tree,lvl);
4264 return operandFromLit (getSize (tree->right->ftype));
4268 sym_link *rtype = operandType (right);
4269 sym_link *ltype = operandType (left);
4270 if (IS_PTR (rtype) && IS_ITEMP (right)
4271 && right->isaddr && compareType (rtype->next, ltype) == 1)
4272 right = geniCodeRValue (right, TRUE);
4274 right = geniCodeRValue (right, FALSE);
4276 geniCodeAssign (left, right, 0, 1);
4281 geniCodeAssign (left,
4282 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4284 geniCodeRValue (right, FALSE),
4285 getResultTypeFromType (tree->ftype)),
4290 geniCodeAssign (left,
4291 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4293 geniCodeRValue (right, FALSE),
4294 getResultTypeFromType (tree->ftype)),
4298 geniCodeAssign (left,
4299 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4301 geniCodeRValue (right, FALSE),
4302 getResultTypeFromType (tree->ftype)),
4306 sym_link *rtype = operandType (right);
4307 sym_link *ltype = operandType (left);
4308 if (IS_PTR (rtype) && IS_ITEMP (right)
4309 && right->isaddr && compareType (rtype->next, ltype) == 1)
4310 right = geniCodeRValue (right, TRUE);
4312 right = geniCodeRValue (right, FALSE);
4315 return geniCodeAssign (left,
4316 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4319 getResultTypeFromType (tree->ftype),
4325 sym_link *rtype = operandType (right);
4326 sym_link *ltype = operandType (left);
4327 if (IS_PTR (rtype) && IS_ITEMP (right)
4328 && right->isaddr && compareType (rtype->next, ltype) == 1)
4330 right = geniCodeRValue (right, TRUE);
4334 right = geniCodeRValue (right, FALSE);
4337 geniCodeAssign (left,
4338 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4341 getResultTypeFromType (tree->ftype)),
4346 geniCodeAssign (left,
4347 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4349 geniCodeRValue (right, FALSE),
4350 getResultTypeFromType (tree->ftype)),
4354 geniCodeAssign (left,
4355 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4357 geniCodeRValue (right, FALSE)), 0, 1);
4360 geniCodeAssign (left,
4361 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4363 geniCodeRValue (right, FALSE),
4365 operandType (left)), 0, 1);
4368 geniCodeAssign (left,
4369 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4371 geniCodeRValue (right, FALSE),
4373 operandType (left)), 0, 1);
4376 geniCodeAssign (left,
4377 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4379 geniCodeRValue (right, FALSE),
4381 operandType (left)), 0, 1);
4383 return geniCodeRValue (right, FALSE);
4386 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4389 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4390 return ast2iCode (tree->right,lvl+1);
4393 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4394 return ast2iCode (tree->right,lvl+1);
4397 geniCodeFunctionBody (tree,lvl);
4401 geniCodeReturn (right);
4405 geniCodeIfx (tree,lvl);
4409 geniCodeSwitch (tree,lvl);
4413 geniCodeInline (tree);
4417 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4421 geniCodeCritical (tree, lvl);
4427 /*-----------------------------------------------------------------*/
4428 /* reverseICChain - gets from the list and creates a linkedlist */
4429 /*-----------------------------------------------------------------*/
4436 while ((loop = getSet (&iCodeChain)))
4448 /*-----------------------------------------------------------------*/
4449 /* iCodeFromAst - given an ast will convert it to iCode */
4450 /*-----------------------------------------------------------------*/
4452 iCodeFromAst (ast * tree)
4454 returnLabel = newiTempLabel ("_return");
4455 entryLabel = newiTempLabel ("_entry");
4457 return reverseiCChain ();
4460 static const char *opTypeToStr(OPTYPE op)
4464 case SYMBOL: return "symbol";
4465 case VALUE: return "value";
4466 case TYPE: return "type";
4468 return "undefined type";
4472 operand *validateOpType(operand *op,
4479 if (op && op->type == type)
4484 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4485 " expected %s, got %s\n",
4486 macro, args, file, line,
4487 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4489 return op; // never reached, makes compiler happy.