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 */
1628 /* we will use it after all optimizations
1629 and before liveRange calculation */
1630 sym->reqv = newiTempOperand (sym->type, 0);
1631 sym->reqv->key = sym->key;
1632 OP_SYMBOL (sym->reqv)->prereqv = sym;
1633 OP_SYMBOL (sym->reqv)->key = sym->key;
1634 OP_SYMBOL (sym->reqv)->isreqv = 1;
1635 OP_SYMBOL (sym->reqv)->islocal = 1;
1636 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1637 SPIL_LOC (sym->reqv) = sym;
1640 if (!IS_AGGREGATE (sym->type))
1644 op->operand.symOperand = sym;
1647 op->isvolatile = isOperandVolatile (op, TRUE);
1648 op->isGlobal = isOperandGlobal (op);
1649 op->isPtr = IS_PTR (operandType (op));
1650 op->isParm = sym->_isparm;
1655 /* itemp = &[_symbol] */
1657 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1658 IC_LEFT (ic)->type = SYMBOL;
1659 IC_LEFT (ic)->operand.symOperand = sym;
1660 IC_LEFT (ic)->key = sym->key;
1661 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1662 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1663 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1666 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1667 if (IS_ARRAY (sym->type))
1669 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1670 IC_RESULT (ic)->isaddr = 0;
1673 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1677 return IC_RESULT (ic);
1680 /*-----------------------------------------------------------------*/
1681 /* operandFromValue - creates an operand from value */
1682 /*-----------------------------------------------------------------*/
1684 operandFromValue (value * val)
1688 /* if this is a symbol then do the symbol thing */
1690 return operandFromSymbol (val->sym);
1692 /* this is not a symbol */
1695 op->operand.valOperand = val;
1696 op->isLiteral = isOperandLiteral (op);
1700 /*-----------------------------------------------------------------*/
1701 /* operandFromLink - operand from typeChain */
1702 /*-----------------------------------------------------------------*/
1704 operandFromLink (sym_link * type)
1708 /* operand from sym_link */
1714 op->operand.typeOperand = copyLinkChain (type);
1718 /*-----------------------------------------------------------------*/
1719 /* operandFromLit - makes an operand from a literal value */
1720 /*-----------------------------------------------------------------*/
1722 operandFromLit (double i)
1724 return operandFromValue (valueFromLit (i));
1727 /*-----------------------------------------------------------------*/
1728 /* operandFromAst - creates an operand from an ast */
1729 /*-----------------------------------------------------------------*/
1731 operandFromAst (ast * tree,int lvl)
1737 /* depending on type do */
1741 return ast2iCode (tree,lvl+1);
1745 return operandFromValue (tree->opval.val);
1749 return operandFromLink (tree->opval.lnk);
1756 /* Just to keep the compiler happy */
1757 return (operand *) 0;
1760 /*-----------------------------------------------------------------*/
1761 /* setOperandType - sets the operand's type to the given type */
1762 /*-----------------------------------------------------------------*/
1764 setOperandType (operand * op, sym_link * type)
1766 /* depending on the type of operand */
1771 op->operand.valOperand->etype =
1772 getSpec (op->operand.valOperand->type =
1773 copyLinkChain (type));
1777 if (op->operand.symOperand->isitmp)
1778 op->operand.symOperand->etype =
1779 getSpec (op->operand.symOperand->type =
1780 copyLinkChain (type));
1782 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1783 "attempt to modify type of source");
1787 op->operand.typeOperand = copyLinkChain (type);
1793 /*-----------------------------------------------------------------*/
1794 /* Get size in byte of ptr need to access an array */
1795 /*-----------------------------------------------------------------*/
1797 getArraySizePtr (operand * op)
1799 sym_link *ltype = operandType(op);
1803 int size = getSize(ltype);
1804 return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1809 sym_link *letype = getSpec(ltype);
1810 switch (PTR_TYPE (SPEC_OCLS (letype)))
1822 if (GPTRSIZE > FPTRSIZE)
1823 return (GPTRSIZE-1);
1834 /*-----------------------------------------------------------------*/
1835 /* perform "usual unary conversions" */
1836 /*-----------------------------------------------------------------*/
1839 usualUnaryConversions (operand * op)
1841 if (IS_INTEGRAL (operandType (op)))
1843 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1846 return geniCodeCast (INTTYPE, op, TRUE);
1853 /*-----------------------------------------------------------------*/
1854 /* perform "usual binary conversions" */
1855 /*-----------------------------------------------------------------*/
1858 usualBinaryConversions (operand ** op1, operand ** op2,
1859 RESULT_TYPE resultType, int op)
1862 sym_link *rtype = operandType (*op2);
1863 sym_link *ltype = operandType (*op1);
1865 ctype = computeType (ltype, rtype, resultType, op);
1872 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1874 /* one byte operations: keep signedness for code generator */
1882 *op1 = geniCodeCast (ctype, *op1, TRUE);
1883 *op2 = geniCodeCast (ctype, *op2, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* geniCodeValueAtAddress - generate intermeditate code for value */
1891 /*-----------------------------------------------------------------*/
1893 geniCodeRValue (operand * op, bool force)
1896 sym_link *type = operandType (op);
1897 sym_link *etype = getSpec (type);
1899 /* if this is an array & already */
1900 /* an address then return this */
1901 if (IS_AGGREGATE (type) ||
1902 (IS_PTR (type) && !force && !op->isaddr))
1903 return operandFromOperand (op);
1905 /* if this is not an address then must be */
1906 /* rvalue already so return this one */
1910 /* if this is not a temp symbol then */
1911 if (!IS_ITEMP (op) &&
1913 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1915 op = operandFromOperand (op);
1920 if (IS_SPEC (type) &&
1921 IS_TRUE_SYMOP (op) &&
1922 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1923 (options.model == MODEL_FLAT24) ))
1925 op = operandFromOperand (op);
1930 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1931 if (IS_PTR (type) && op->isaddr && force)
1934 type = copyLinkChain (type);
1936 IC_RESULT (ic) = newiTempOperand (type, 1);
1937 IC_RESULT (ic)->isaddr = 0;
1939 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1943 return IC_RESULT (ic);
1946 /*-----------------------------------------------------------------*/
1947 /* geniCodeCast - changes the value from one type to another */
1948 /*-----------------------------------------------------------------*/
1950 geniCodeCast (sym_link * type, operand * op, bool implicit)
1954 sym_link *opetype = getSpec (optype = operandType (op));
1958 /* one of them has size zero then error */
1959 if (IS_VOID (optype))
1961 werror (E_CAST_ZERO);
1965 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1967 geniCodeArray2Ptr (op);
1971 /* if the operand is already the desired type then do nothing */
1972 if (compareType (type, optype) == 1)
1975 /* if this is a literal then just change the type & return */
1976 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1978 return operandFromValue (valCastLiteral (type,
1979 operandLitValue (op)));
1982 /* if casting to/from pointers, do some checking */
1983 if (IS_PTR(type)) { // to a pointer
1984 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1985 if (IS_INTEGRAL(optype)) {
1986 // maybe this is NULL, than it's ok.
1987 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1988 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1989 // no way to set the storage
1990 if (IS_LITERAL(optype)) {
1991 werror(E_LITERAL_GENERIC);
1994 werror(E_NONPTR2_GENPTR);
1997 } else if (implicit) {
1998 werror(W_INTEGRAL2PTR_NOCAST);
2003 // shouldn't do that with float, array or structure unless to void
2004 if (!IS_VOID(getSpec(type)) &&
2005 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2006 werror(E_INCOMPAT_TYPES);
2010 } else { // from a pointer to a pointer
2011 if (IS_GENPTR(type) && IS_VOID(type->next))
2012 { // cast to void* is always allowed
2014 else if (IS_GENPTR(optype) && IS_VOID(optype->next))
2015 { // cast from void* is always allowed
2017 else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
2018 // if not a pointer to a function
2019 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2020 if (implicit) { // if not to generic, they have to match
2021 if (!IS_GENPTR(type) &&
2022 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
2023 ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
2027 werror(E_INCOMPAT_PTYPES);
2034 } else { // to a non pointer
2035 if (IS_PTR(optype)) { // from a pointer
2036 if (implicit) { // sneaky
2037 if (IS_INTEGRAL(type)) {
2038 werror(W_PTR2INTEGRAL_NOCAST);
2040 } else { // shouldn't do that with float, array or structure
2041 werror(E_INCOMPAT_TYPES);
2048 printFromToType (optype, type);
2051 /* if they are the same size create an assignment */
2053 /* This seems very dangerous to me, since there are several */
2054 /* optimizations (for example, gcse) that don't notice the */
2055 /* cast hidden in this assignement and may simplify an */
2056 /* iCode to use the original (uncasted) operand. */
2057 /* Unfortunately, other things break when this cast is */
2058 /* made explicit. Need to fix this someday. */
2059 /* -- EEP, 2004/01/21 */
2060 if (getSize (type) == getSize (optype) &&
2061 !IS_BITFIELD (type) &&
2063 !IS_FLOAT (optype) &&
2065 !IS_FIXED (optype) &&
2066 ((IS_SPEC (type) && IS_SPEC (optype)) ||
2067 (!IS_SPEC (type) && !IS_SPEC (optype))))
2069 ic = newiCode ('=', NULL, op);
2070 IC_RESULT (ic) = newiTempOperand (type, 0);
2071 if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
2072 SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
2073 IC_RESULT (ic)->isaddr = 0;
2077 ic = newiCode (CAST, operandFromLink (type),
2078 geniCodeRValue (op, FALSE));
2080 IC_RESULT (ic) = newiTempOperand (type, 0);
2083 /* preserve the storage class & output class */
2084 /* of the original variable */
2085 restype = getSpec (operandType (IC_RESULT (ic)));
2086 if (!IS_LITERAL(opetype) &&
2089 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2090 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2093 return IC_RESULT (ic);
2096 /*-----------------------------------------------------------------*/
2097 /* geniCodeLabel - will create a Label */
2098 /*-----------------------------------------------------------------*/
2100 geniCodeLabel (symbol * label)
2104 ic = newiCodeLabelGoto (LABEL, label);
2108 /*-----------------------------------------------------------------*/
2109 /* geniCodeGoto - will create a Goto */
2110 /*-----------------------------------------------------------------*/
2112 geniCodeGoto (symbol * label)
2116 ic = newiCodeLabelGoto (GOTO, label);
2120 /*-----------------------------------------------------------------*/
2121 /* geniCodeMultiply - gen intermediate code for multiplication */
2122 /*-----------------------------------------------------------------*/
2124 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2131 /* if they are both literal then we know the result */
2132 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2133 return operandFromValue (valMult (left->operand.valOperand,
2134 right->operand.valOperand));
2136 if (IS_LITERAL(retype)) {
2137 p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2140 resType = usualBinaryConversions (&left, &right, resultType, '*');
2142 rtype = operandType (right);
2143 retype = getSpec (rtype);
2144 ltype = operandType (left);
2145 letype = getSpec (ltype);
2148 /* if the right is a literal & power of 2 */
2149 /* then make it a left shift */
2150 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2151 efficient in most cases than 2 bytes result = 2 bytes << literal
2152 if port has 1 byte muldiv */
2153 if (p2 && !IS_FLOAT (letype) && !IS_FIXED (letype)
2154 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2155 && (port->support.muldiv == 1))
2156 && strcmp (port->target, "pic16") != 0 /* don't shift for pic */
2157 && strcmp (port->target, "pic14") != 0)
2159 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2161 /* LEFT_OP need same size for left and result, */
2162 left = geniCodeCast (resType, left, TRUE);
2163 ltype = operandType (left);
2165 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2169 ic = newiCode ('*', left, right); /* normal multiplication */
2170 /* if the size left or right > 1 then support routine */
2171 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2175 IC_RESULT (ic) = newiTempOperand (resType, 1);
2178 return IC_RESULT (ic);
2181 /*-----------------------------------------------------------------*/
2182 /* geniCodeDivision - gen intermediate code for division */
2183 /*-----------------------------------------------------------------*/
2185 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2190 sym_link *rtype = operandType (right);
2191 sym_link *retype = getSpec (rtype);
2192 sym_link *ltype = operandType (left);
2193 sym_link *letype = getSpec (ltype);
2195 resType = usualBinaryConversions (&left, &right, resultType, '/');
2197 /* if the right is a literal & power of 2
2198 and left is unsigned then make it a
2200 if (IS_LITERAL (retype) &&
2201 !IS_FLOAT (letype) &&
2202 !IS_FIXED (letype) &&
2203 IS_UNSIGNED(letype) &&
2204 (p2 = powof2 ((TYPE_UDWORD)
2205 floatFromVal (right->operand.valOperand)))) {
2206 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2210 ic = newiCode ('/', left, right); /* normal division */
2211 /* if the size left or right > 1 then support routine */
2212 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2215 IC_RESULT (ic) = newiTempOperand (resType, 0);
2218 return IC_RESULT (ic);
2220 /*-----------------------------------------------------------------*/
2221 /* geniCodeModulus - gen intermediate code for modulus */
2222 /*-----------------------------------------------------------------*/
2224 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2230 /* if they are both literal then we know the result */
2231 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2232 return operandFromValue (valMod (left->operand.valOperand,
2233 right->operand.valOperand));
2235 resType = usualBinaryConversions (&left, &right, resultType, '%');
2237 /* now they are the same size */
2238 ic = newiCode ('%', left, right);
2240 /* if the size left or right > 1 then support routine */
2241 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2243 IC_RESULT (ic) = newiTempOperand (resType, 0);
2246 return IC_RESULT (ic);
2249 /*-----------------------------------------------------------------*/
2250 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2251 /*-----------------------------------------------------------------*/
2253 geniCodePtrPtrSubtract (operand * left, operand * right)
2259 /* if they are both literals then */
2260 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2262 result = operandFromValue (valMinus (left->operand.valOperand,
2263 right->operand.valOperand));
2267 ic = newiCode ('-', left, right);
2269 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2273 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2277 // should we really do this? is this ANSI?
2278 return geniCodeDivision (result,
2279 operandFromLit (getSize (ltype->next)),
2283 /*-----------------------------------------------------------------*/
2284 /* geniCodeSubtract - generates code for subtraction */
2285 /*-----------------------------------------------------------------*/
2287 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2294 /* if they both pointers then */
2295 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2296 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2297 return geniCodePtrPtrSubtract (left, right);
2299 /* if they are both literal then we know the result */
2300 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2301 && left->isLiteral && right->isLiteral)
2302 return operandFromValue (valMinus (left->operand.valOperand,
2303 right->operand.valOperand));
2305 /* if left is an array or pointer */
2306 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2308 isarray = left->isaddr;
2309 right = geniCodeMultiply (right,
2310 operandFromLit (getSize (ltype->next)),
2311 (getArraySizePtr(left) >= INTSIZE) ?
2314 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2317 { /* make them the same size */
2318 resType = usualBinaryConversions (&left, &right, resultType, '-');
2321 ic = newiCode ('-', left, right);
2323 IC_RESULT (ic) = newiTempOperand (resType, 1);
2324 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2326 /* if left or right is a float */
2327 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2328 || IS_FIXED (ltype) || IS_FIXED (rtype))
2332 return IC_RESULT (ic);
2335 /*-----------------------------------------------------------------*/
2336 /* geniCodeAdd - generates iCode for addition */
2337 /*-----------------------------------------------------------------*/
2339 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2348 /* if the right side is LITERAL zero */
2349 /* return the left side */
2350 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2353 /* if left is literal zero return right */
2354 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2357 /* if left is a pointer then size */
2358 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2360 isarray = left->isaddr;
2361 // there is no need to multiply with 1
2362 if (getSize (ltype->next) != 1)
2364 size = operandFromLit (getSize (ltype->next));
2365 SPEC_USIGN (getSpec (operandType (size))) = 1;
2366 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2367 right = geniCodeMultiply (right,
2369 (getArraySizePtr(left) >= INTSIZE) ?
2372 /* Even if right is a 'unsigned char',
2373 the result will be a 'signed int' due to the promotion rules.
2374 It doesn't make sense when accessing arrays, so let's fix it here: */
2376 SPEC_USIGN (getSpec (operandType (right))) = 1;
2378 resType = copyLinkChain (ltype);
2381 { // make them the same size
2382 resType = usualBinaryConversions (&left, &right, resultType, '+');
2385 /* if they are both literals then we know */
2386 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2387 && left->isLiteral && right->isLiteral)
2388 return operandFromValue (valPlus (valFromType (ltype),
2389 valFromType (rtype)));
2391 ic = newiCode ('+', left, right);
2393 IC_RESULT (ic) = newiTempOperand (resType, 1);
2394 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2396 /* if left or right is a float then support
2398 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2399 || IS_FIXED (ltype) || IS_FIXED (rtype))
2404 return IC_RESULT (ic);
2408 /*-----------------------------------------------------------------*/
2409 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2410 /*-----------------------------------------------------------------*/
2412 aggrToPtr (sym_link * type, bool force)
2417 if (IS_PTR (type) && !force)
2420 etype = getSpec (type);
2421 ptype = newLink (DECLARATOR);
2425 /* set the pointer depending on the storage class */
2426 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2430 /*------------------------------------------------------------------*/
2431 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2432 /*------------------------------------------------------------------*/
2434 aggrToPtrDclType (sym_link * type, bool force)
2436 if (IS_PTR (type) && !force)
2437 return DCL_TYPE (type);
2439 /* return the pointer depending on the storage class */
2440 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2443 /*-----------------------------------------------------------------*/
2444 /* geniCodeArray2Ptr - array to pointer */
2445 /*-----------------------------------------------------------------*/
2447 geniCodeArray2Ptr (operand * op)
2449 sym_link *optype = operandType (op);
2450 sym_link *opetype = getSpec (optype);
2452 /* set the pointer depending on the storage class */
2453 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2460 /*-----------------------------------------------------------------*/
2461 /* geniCodeArray - array access */
2462 /*-----------------------------------------------------------------*/
2464 geniCodeArray (operand * left, operand * right, int lvl)
2468 sym_link *ltype = operandType (left);
2473 if (IS_PTR (ltype->next) && left->isaddr)
2475 left = geniCodeRValue (left, FALSE);
2478 return geniCodeDerefPtr (geniCodeAdd (left,
2480 (getArraySizePtr(left) >= INTSIZE) ?
2486 size = operandFromLit (getSize (ltype->next));
2487 SPEC_USIGN (getSpec (operandType (size))) = 1;
2488 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2489 right = geniCodeMultiply (right,
2491 (getArraySizePtr(left) >= INTSIZE) ?
2494 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2495 It doesn't make sense when accessing arrays, so let's fix it here: */
2497 SPEC_USIGN (getSpec (operandType (right))) = 1;
2498 /* we can check for limits here */
2499 /* already done in SDCCast.c
2500 if (isOperandLiteral (right) &&
2503 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2505 werror (W_IDX_OUT_OF_BOUNDS,
2506 (int) operandLitValue (right) / getSize (ltype->next),
2511 ic = newiCode ('+', left, right);
2513 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2514 !IS_AGGREGATE (ltype->next) &&
2515 !IS_PTR (ltype->next))
2516 ? ltype : ltype->next), 0);
2518 if (!IS_AGGREGATE (ltype->next))
2520 IC_RESULT (ic)->isaddr = 1;
2521 IC_RESULT (ic)->aggr2ptr = 1;
2525 return IC_RESULT (ic);
2528 /*-----------------------------------------------------------------*/
2529 /* geniCodeStruct - generates intermediate code for structures */
2530 /*-----------------------------------------------------------------*/
2532 geniCodeStruct (operand * left, operand * right, bool islval)
2535 sym_link *type = operandType (left);
2536 sym_link *etype = getSpec (type);
2538 symbol *element = getStructElement (SPEC_STRUCT (etype),
2539 right->operand.symOperand);
2541 wassert(IS_SYMOP(right));
2543 /* add the offset */
2544 ic = newiCode ('+', left, operandFromLit (element->offset));
2546 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2548 /* preserve the storage & output class of the struct */
2549 /* as well as the volatile attribute */
2550 retype = getSpec (operandType (IC_RESULT (ic)));
2551 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2552 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2553 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2554 SPEC_CONST (retype) |= SPEC_CONST (etype);
2556 if (IS_PTR (element->type))
2557 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2559 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2562 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2565 /*-----------------------------------------------------------------*/
2566 /* geniCodePostInc - generate int code for Post increment */
2567 /*-----------------------------------------------------------------*/
2569 geniCodePostInc (operand * op)
2573 sym_link *optype = operandType (op);
2575 operand *rv = (IS_ITEMP (op) ?
2576 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2578 sym_link *rvtype = operandType (rv);
2581 /* if this is not an address we have trouble */
2584 werror (E_LVALUE_REQUIRED, "++");
2588 rOp = newiTempOperand (rvtype, 0);
2589 OP_SYMBOL(rOp)->noSpilLoc = 1;
2592 OP_SYMBOL(rv)->noSpilLoc = 1;
2594 geniCodeAssign (rOp, rv, 0, 0);
2596 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2598 werror(W_SIZEOF_VOID);
2599 if (IS_FLOAT (rvtype))
2600 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2602 if (IS_FIXED16X16 (rvtype))
2603 ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2605 ic = newiCode ('+', rv, operandFromLit (size));
2607 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2610 geniCodeAssign (op, result, 0, 0);
2616 /*-----------------------------------------------------------------*/
2617 /* geniCodePreInc - generate code for preIncrement */
2618 /*-----------------------------------------------------------------*/
2620 geniCodePreInc (operand * op, bool lvalue)
2623 sym_link *optype = operandType (op);
2624 operand *rop = (IS_ITEMP (op) ?
2625 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2627 sym_link *roptype = operandType (rop);
2633 werror (E_LVALUE_REQUIRED, "++");
2637 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2639 werror(W_SIZEOF_VOID);
2640 if (IS_FLOAT (roptype))
2641 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2643 if (IS_FIXED16X16 (roptype))
2644 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2646 ic = newiCode ('+', rop, operandFromLit (size));
2647 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2650 (void) geniCodeAssign (op, result, 0, 0);
2651 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2657 /*-----------------------------------------------------------------*/
2658 /* geniCodePostDec - generates code for Post decrement */
2659 /*-----------------------------------------------------------------*/
2661 geniCodePostDec (operand * op)
2665 sym_link *optype = operandType (op);
2667 operand *rv = (IS_ITEMP (op) ?
2668 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2670 sym_link *rvtype = operandType (rv);
2673 /* if this is not an address we have trouble */
2676 werror (E_LVALUE_REQUIRED, "--");
2680 rOp = newiTempOperand (rvtype, 0);
2681 OP_SYMBOL(rOp)->noSpilLoc = 1;
2684 OP_SYMBOL(rv)->noSpilLoc = 1;
2686 geniCodeAssign (rOp, rv, 0, 0);
2688 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2690 werror(W_SIZEOF_VOID);
2691 if (IS_FLOAT (rvtype))
2692 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2694 if (IS_FIXED16X16 (rvtype))
2695 ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2697 ic = newiCode ('-', rv, operandFromLit (size));
2699 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2702 geniCodeAssign (op, result, 0, 0);
2708 /*-----------------------------------------------------------------*/
2709 /* geniCodePreDec - generate code for pre decrement */
2710 /*-----------------------------------------------------------------*/
2712 geniCodePreDec (operand * op, bool lvalue)
2715 sym_link *optype = operandType (op);
2716 operand *rop = (IS_ITEMP (op) ?
2717 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2719 sym_link *roptype = operandType (rop);
2725 werror (E_LVALUE_REQUIRED, "--");
2729 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2731 werror(W_SIZEOF_VOID);
2732 if (IS_FLOAT (roptype))
2733 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2735 if (IS_FIXED16X16 (roptype))
2736 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2738 ic = newiCode ('-', rop, operandFromLit (size));
2739 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2742 (void) geniCodeAssign (op, result, 0, 0);
2743 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2750 /*-----------------------------------------------------------------*/
2751 /* geniCodeBitwise - gen int code for bitWise operators */
2752 /*-----------------------------------------------------------------*/
2754 geniCodeBitwise (operand * left, operand * right,
2755 int oper, sym_link * resType)
2759 left = geniCodeCast (resType, left, TRUE);
2760 right = geniCodeCast (resType, right, TRUE);
2762 ic = newiCode (oper, left, right);
2763 IC_RESULT (ic) = newiTempOperand (resType, 0);
2766 return IC_RESULT (ic);
2769 /*-----------------------------------------------------------------*/
2770 /* geniCodeAddressOf - gens icode for '&' address of operator */
2771 /*-----------------------------------------------------------------*/
2773 geniCodeAddressOf (operand * op)
2777 sym_link *optype = operandType (op);
2778 sym_link *opetype = getSpec (optype);
2780 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2782 op = operandFromOperand (op);
2787 /* lvalue check already done in decorateType */
2788 /* this must be a lvalue */
2789 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2790 /* werror (E_LVALUE_REQUIRED,"&"); */
2794 p = newLink (DECLARATOR);
2796 /* set the pointer depending on the storage class */
2797 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2799 p->next = copyLinkChain (optype);
2801 /* if already a temp */
2804 setOperandType (op, p);
2809 /* other wise make this of the type coming in */
2810 ic = newiCode (ADDRESS_OF, op, NULL);
2811 IC_RESULT (ic) = newiTempOperand (p, 1);
2812 IC_RESULT (ic)->isaddr = 0;
2814 return IC_RESULT (ic);
2816 /*-----------------------------------------------------------------*/
2817 /* setOClass - sets the output class depending on the pointer type */
2818 /*-----------------------------------------------------------------*/
2820 setOClass (sym_link * ptr, sym_link * spec)
2822 switch (DCL_TYPE (ptr))
2825 SPEC_OCLS (spec) = data;
2829 SPEC_OCLS (spec) = generic;
2833 SPEC_OCLS (spec) = xdata;
2837 SPEC_OCLS (spec) = code;
2841 SPEC_OCLS (spec) = idata;
2845 SPEC_OCLS (spec) = xstack;
2849 SPEC_OCLS (spec) = eeprom;
2858 /*-----------------------------------------------------------------*/
2859 /* geniCodeDerefPtr - dereference pointer with '*' */
2860 /*-----------------------------------------------------------------*/
2862 geniCodeDerefPtr (operand * op,int lvl)
2864 sym_link *rtype, *retype;
2865 sym_link *optype = operandType (op);
2867 // if this is an array then array access
2868 if (IS_ARRAY (optype)) {
2869 // don't worry, this will be optimized out later
2870 return geniCodeArray (op, operandFromLit (0), lvl);
2873 // just in case someone screws up
2874 wassert (IS_PTR (optype));
2876 if (IS_TRUE_SYMOP (op))
2879 op = geniCodeRValue (op, TRUE);
2882 /* now get rid of the pointer part */
2883 if (isLvaluereq(lvl) && IS_ITEMP (op))
2885 retype = getSpec (rtype = copyLinkChain (optype));
2889 retype = getSpec (rtype = copyLinkChain (optype->next));
2890 /* outputclass needs 2b updated */
2891 setOClass (optype, retype);
2894 op->isGptr = IS_GENPTR (optype);
2896 op->isaddr = (IS_PTR (rtype) ||
2897 IS_STRUCT (rtype) ||
2903 if (!isLvaluereq(lvl))
2904 op = geniCodeRValue (op, TRUE);
2906 setOperandType (op, rtype);
2911 /*-----------------------------------------------------------------*/
2912 /* geniCodeUnaryMinus - does a unary minus of the operand */
2913 /*-----------------------------------------------------------------*/
2915 geniCodeUnaryMinus (operand * op)
2918 sym_link *optype = operandType (op);
2920 if (IS_LITERAL (optype))
2921 return operandFromLit (-floatFromVal (op->operand.valOperand));
2923 ic = newiCode (UNARYMINUS, op, NULL);
2924 IC_RESULT (ic) = newiTempOperand (optype, 0);
2926 return IC_RESULT (ic);
2929 /*-----------------------------------------------------------------*/
2930 /* geniCodeLeftShift - gen i code for left shift */
2931 /*-----------------------------------------------------------------*/
2933 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2938 ic = newiCode (LEFT_OP, left, right);
2940 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2941 IC_RESULT (ic) = newiTempOperand (resType, 0);
2943 return IC_RESULT (ic);
2946 /*-----------------------------------------------------------------*/
2947 /* geniCodeRightShift - gen i code for right shift */
2948 /*-----------------------------------------------------------------*/
2950 geniCodeRightShift (operand * left, operand * right)
2954 ic = newiCode (RIGHT_OP, left, right);
2955 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2957 return IC_RESULT (ic);
2960 /*-----------------------------------------------------------------*/
2961 /* geniCodeLogic- logic code */
2962 /*-----------------------------------------------------------------*/
2964 geniCodeLogic (operand * left, operand * right, int op)
2968 sym_link *rtype = operandType (right);
2969 sym_link *ltype = operandType (left);
2971 /* left is integral type and right is literal then
2972 check if the literal value is within bounds */
2973 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2975 checkConstantRange(ltype,
2976 OP_VALUE(right), "compare operation", 1);
2979 /* if one operand is a pointer and the other is a literal generic void pointer,
2980 change the type of the literal generic void pointer to match the other pointer */
2981 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2982 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2984 /* find left's definition */
2985 ic = (iCode *) setFirstItem (iCodeChain);
2988 if (((ic->op == CAST) || (ic->op == '='))
2989 && isOperandEqual(left, IC_RESULT (ic)))
2992 ic = setNextItem (iCodeChain);
2994 /* if casting literal to generic pointer, then cast to rtype instead */
2995 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2997 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2998 ltype = operandType(left);
3001 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
3002 && IS_PTR (ltype) && !IS_GENPTR(ltype))
3004 /* find right's definition */
3005 ic = (iCode *) setFirstItem (iCodeChain);
3008 if (((ic->op == CAST) || (ic->op == '='))
3009 && isOperandEqual(right, IC_RESULT (ic)))
3012 ic = setNextItem (iCodeChain);
3014 /* if casting literal to generic pointer, then cast to rtype instead */
3015 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
3017 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
3018 rtype = operandType(right);
3022 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
3024 ic = newiCode (op, left, right);
3025 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
3027 /* if comparing float
3028 and not a '==' || '!=' || '&&' || '||' (these
3030 if (IS_FLOAT(ctype) &&
3037 /* if comparing a fixed type use support functions */
3038 if (IS_FIXED(ctype))
3042 return IC_RESULT (ic);
3045 /*-----------------------------------------------------------------*/
3046 /* geniCodeLogicAndOr - && || operations */
3047 /*-----------------------------------------------------------------*/
3049 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 type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
3097 result = newiTempOperand (type, 1);
3099 geniCodeLabel (falseLabel);
3100 geniCodeAssign (result, operandFromLit (0), 0, 0);
3101 /* generate an unconditional goto */
3102 geniCodeGoto (exitLabel);
3104 geniCodeLabel (trueLabel);
3105 geniCodeAssign (result, operandFromLit (1), 0, 0);
3107 geniCodeLabel (exitLabel);
3112 /*-----------------------------------------------------------------*/
3113 /* geniCodeUnary - for a generic unary operation */
3114 /*-----------------------------------------------------------------*/
3116 geniCodeUnary (operand * op, int oper)
3118 iCode *ic = newiCode (oper, op, NULL);
3120 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3122 return IC_RESULT (ic);
3125 /*-----------------------------------------------------------------*/
3126 /* geniCodeConditional - geniCode for '?' ':' operation */
3127 /*-----------------------------------------------------------------*/
3129 geniCodeConditional (ast * tree,int lvl)
3132 symbol *falseLabel = newiTempLabel (NULL);
3133 symbol *exitLabel = newiTempLabel (NULL);
3134 operand *cond = ast2iCode (tree->left,lvl+1);
3135 operand *true, *false, *result;
3137 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3141 true = ast2iCode (tree->right->left,lvl+1);
3143 /* move the value to a new Operand */
3144 result = newiTempOperand (tree->right->ftype, 0);
3145 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3147 /* generate an unconditional goto */
3148 geniCodeGoto (exitLabel);
3150 /* now for the right side */
3151 geniCodeLabel (falseLabel);
3153 false = ast2iCode (tree->right->right,lvl+1);
3154 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3156 /* create the exit label */
3157 geniCodeLabel (exitLabel);
3162 /*-----------------------------------------------------------------*/
3163 /* geniCodeAssign - generate code for assignment */
3164 /*-----------------------------------------------------------------*/
3166 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3169 sym_link *ltype = operandType (left);
3170 sym_link *rtype = operandType (right);
3172 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3174 werror (E_LVALUE_REQUIRED, "assignment");
3178 /* left is integral type and right is literal then
3179 check if the literal value is within bounds */
3180 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3182 checkConstantRange(ltype,
3183 OP_VALUE(right), "= operation", 0);
3186 /* if the left & right type don't exactly match */
3187 /* if pointer set then make sure the check is
3188 done with the type & not the pointer */
3189 /* then cast rights type to left */
3191 /* first check the type for pointer assignement */
3192 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3193 compareType (ltype, rtype) <= 0)
3195 if (compareType (ltype->next, rtype) < 0)
3196 right = geniCodeCast (ltype->next, right, TRUE);
3198 else if (compareType (ltype, rtype) < 0)
3199 right = geniCodeCast (ltype, right, TRUE);
3201 /* If left is a true symbol & ! volatile
3202 create an assignment to temporary for
3203 the right & then assign this temporary
3204 to the symbol. This is SSA (static single
3205 assignment). Isn't it simple and folks have
3206 published mountains of paper on it */
3207 if (IS_TRUE_SYMOP (left) &&
3208 !isOperandVolatile (left, FALSE) &&
3209 isOperandGlobal (left))
3213 if (IS_TRUE_SYMOP (right))
3214 sym = OP_SYMBOL (right);
3215 ic = newiCode ('=', NULL, right);
3216 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3217 SPIL_LOC (right) = sym;
3221 ic = newiCode ('=', NULL, right);
3222 IC_RESULT (ic) = left;
3225 /* if left isgptr flag is set then support
3226 routine will be required */
3230 ic->nosupdate = nosupdate;
3234 /*-----------------------------------------------------------------*/
3235 /* geniCodeDummyRead - generate code for dummy read */
3236 /*-----------------------------------------------------------------*/
3238 geniCodeDummyRead (operand * op)
3241 sym_link *type = operandType (op);
3243 if (!IS_VOLATILE(type))
3246 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3252 /*-----------------------------------------------------------------*/
3253 /* geniCodeSEParms - generate code for side effecting fcalls */
3254 /*-----------------------------------------------------------------*/
3256 geniCodeSEParms (ast * parms,int lvl)
3261 if (parms->type == EX_OP && parms->opval.op == PARAM)
3263 geniCodeSEParms (parms->left,lvl);
3264 geniCodeSEParms (parms->right,lvl);
3268 /* hack don't like this but too lazy to think of
3270 if (IS_ADDRESS_OF_OP (parms))
3271 parms->left->lvalue = 1;
3273 if (IS_CAST_OP (parms) &&
3274 IS_PTR (parms->ftype) &&
3275 IS_ADDRESS_OF_OP (parms->right))
3276 parms->right->left->lvalue = 1;
3278 parms->opval.oprnd =
3279 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3281 parms->type = EX_OPERAND;
3282 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3283 SPEC_ARGREG(parms->ftype);
3286 /*-----------------------------------------------------------------*/
3287 /* geniCodeParms - generates parameters */
3288 /*-----------------------------------------------------------------*/
3290 geniCodeParms (ast * parms, value *argVals, int *stack,
3291 sym_link * ftype, int lvl)
3299 if (argVals==NULL) {
3301 argVals = FUNC_ARGS (ftype);
3304 /* if this is a param node then do the left & right */
3305 if (parms->type == EX_OP && parms->opval.op == PARAM)
3307 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3308 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3312 /* get the parameter value */
3313 if (parms->type == EX_OPERAND)
3314 pval = parms->opval.oprnd;
3317 /* maybe this else should go away ?? */
3318 /* hack don't like this but too lazy to think of
3320 if (IS_ADDRESS_OF_OP (parms))
3321 parms->left->lvalue = 1;
3323 if (IS_CAST_OP (parms) &&
3324 IS_PTR (parms->ftype) &&
3325 IS_ADDRESS_OF_OP (parms->right))
3326 parms->right->left->lvalue = 1;
3328 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3331 /* if register parm then make it a send */
3332 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3333 IFFUNC_ISBUILTIN(ftype))
3335 ic = newiCode (SEND, pval, NULL);
3336 ic->argreg = SPEC_ARGREG(parms->etype);
3337 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3342 /* now decide whether to push or assign */
3343 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3347 operand *top = operandFromSymbol (argVals->sym);
3348 /* clear useDef and other bitVectors */
3349 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3350 geniCodeAssign (top, pval, 1, 0);
3354 sym_link *p = operandType (pval);
3356 ic = newiCode (IPUSH, pval, NULL);
3358 /* update the stack adjustment */
3359 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3364 argVals=argVals->next;
3368 /*-----------------------------------------------------------------*/
3369 /* geniCodeCall - generates temp code for calling */
3370 /*-----------------------------------------------------------------*/
3372 geniCodeCall (operand * left, ast * parms,int lvl)
3376 sym_link *type, *etype;
3380 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3381 !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3382 werror (E_FUNCTION_EXPECTED);
3383 return operandFromValue(valueFromLit(0));
3386 /* take care of parameters with side-effecting
3387 function calls in them, this is required to take care
3388 of overlaying function parameters */
3389 geniCodeSEParms (parms,lvl);
3391 ftype = operandType (left);
3392 if (IS_FUNCPTR (ftype))
3393 ftype = ftype->next;
3395 /* first the parameters */
3396 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3398 /* now call : if symbol then pcall */
3399 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3400 ic = newiCode (PCALL, left, NULL);
3402 ic = newiCode (CALL, left, NULL);
3405 type = copyLinkChain (ftype->next);
3406 etype = getSpec (type);
3407 SPEC_EXTR (etype) = 0;
3408 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3412 /* stack adjustment after call */
3413 ic->parmBytes = stack;
3418 /*-----------------------------------------------------------------*/
3419 /* geniCodeReceive - generate intermediate code for "receive" */
3420 /*-----------------------------------------------------------------*/
3422 geniCodeReceive (value * args, operand * func)
3424 unsigned char paramByteCounter = 0;
3426 /* 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, func, NULL);
3459 ic->argreg = SPEC_ARGREG(args->etype);
3460 if (ic->argreg == 1) {
3461 currFunc->recvSize = getSize (sym->type);
3463 IC_RESULT (ic) = opr;
3465 /* misuse of parmBytes (normally used for functions)
3466 * to save estimated stack position of this argument.
3467 * Normally this should be zero for RECEIVE iCodes.
3468 * No idea if this causes side effects on other ports. - dw
3470 ic->parmBytes = paramByteCounter;
3472 /* what stack position do we have? */
3473 paramByteCounter += getSize (sym->type);
3482 /*-----------------------------------------------------------------*/
3483 /* geniCodeFunctionBody - create the function body */
3484 /*-----------------------------------------------------------------*/
3486 geniCodeFunctionBody (ast * tree,int lvl)
3493 /* reset the auto generation */
3499 func = ast2iCode (tree->left,lvl+1);
3500 fetype = getSpec (operandType (func));
3502 savelineno = lineno;
3503 lineno = OP_SYMBOL (func)->lineDef;
3504 /* create an entry label */
3505 geniCodeLabel (entryLabel);
3506 lineno = savelineno;
3508 /* create a proc icode */
3509 ic = newiCode (FUNCTION, func, NULL);
3510 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3515 /* for all parameters that are passed
3516 on registers add a "receive" */
3517 geniCodeReceive (tree->values.args, func);
3519 /* generate code for the body */
3520 ast2iCode (tree->right,lvl+1);
3522 /* create a label for return */
3523 geniCodeLabel (returnLabel);
3525 /* now generate the end proc */
3526 ic = newiCode (ENDFUNCTION, func, NULL);
3532 /*-----------------------------------------------------------------*/
3533 /* geniCodeReturn - gen icode for 'return' statement */
3534 /*-----------------------------------------------------------------*/
3536 geniCodeReturn (operand * op)
3540 /* if the operand is present force an rvalue */
3542 op = geniCodeRValue (op, FALSE);
3544 ic = newiCode (RETURN, op, NULL);
3548 /*-----------------------------------------------------------------*/
3549 /* geniCodeIfx - generates code for extended if statement */
3550 /*-----------------------------------------------------------------*/
3552 geniCodeIfx (ast * tree,int lvl)
3555 operand *condition = ast2iCode (tree->left,lvl+1);
3558 /* if condition is null then exit */
3562 condition = geniCodeRValue (condition, FALSE);
3564 cetype = getSpec (operandType (condition));
3565 /* if the condition is a literal */
3566 if (IS_LITERAL (cetype))
3568 if (floatFromVal (condition->operand.valOperand))
3570 if (tree->trueLabel)
3571 geniCodeGoto (tree->trueLabel);
3577 if (tree->falseLabel)
3578 geniCodeGoto (tree->falseLabel);
3585 if (tree->trueLabel)
3587 ic = newiCodeCondition (condition,
3592 if (tree->falseLabel)
3593 geniCodeGoto (tree->falseLabel);
3597 ic = newiCodeCondition (condition,
3604 ast2iCode (tree->right,lvl+1);
3607 /*-----------------------------------------------------------------*/
3608 /* geniCodeJumpTable - tries to create a jump table for switch */
3609 /*-----------------------------------------------------------------*/
3611 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3613 int min, max, cnt = 1;
3620 int needRangeCheck = !optimize.noJTabBoundary
3621 || tree->values.switchVals.swDefault;
3622 sym_link *cetype = getSpec (operandType (cond));
3623 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3624 int sizeofMatchJump, sizeofJumpTable;
3627 if (!tree || !caseVals)
3630 /* the criteria for creating a jump table is */
3631 /* all integer numbers between the maximum & minimum must */
3632 /* be present , the maximum value should not exceed 255 */
3633 /* If not all integer numbers are present the algorithm */
3634 /* inserts jumps to the default label for the missing numbers */
3635 /* and decides later whether it is worth it */
3636 min = (int) floatFromVal (vch = caseVals);
3643 max = (int) floatFromVal (vch);
3645 /* Exit if the range is too large to handle with a jump table. */
3646 if (1 + max - min > port->jumptableCost.maxCount)
3649 switch (getSize (operandType (cond)))
3651 case 1: sizeIndex = 0; break;
3652 case 2: sizeIndex = 1; break;
3653 case 4: sizeIndex = 2; break;
3657 /* Compute the size cost of the range check and subtraction. */
3659 sizeofZeroMinCost = 0;
3663 if (!(min==0 && IS_UNSIGNED (cetype)))
3664 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3665 if (!IS_UNSIGNED (cetype))
3666 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3667 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3670 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3672 /* If the size cost of handling a non-zero minimum exceeds the */
3673 /* cost of extending the range down to zero, then it might be */
3674 /* better to extend the range to zero. */
3675 if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3676 >= (min * port->jumptableCost.sizeofElement))
3678 /* Only extend the jump table if it would still be manageable. */
3679 if (1 + max <= port->jumptableCost.maxCount)
3682 if (IS_UNSIGNED (cetype))
3685 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3689 /* Compute the total size cost of a jump table. */
3690 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3691 + port->jumptableCost.sizeofDispatch
3692 + sizeofMinCost + sizeofMaxCost;
3694 /* Compute the total size cost of a match & jump sequence */
3695 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3697 /* If the size cost of the jump table is uneconomical then exit */
3698 if (sizeofMatchJump < sizeofJumpTable)
3701 /* The jump table is preferable. */
3703 /* First, a label for the default or missing cases. */
3704 if (tree->values.switchVals.swDefault)
3706 SNPRINTF (buffer, sizeof(buffer),
3708 tree->values.switchVals.swNum);
3712 SNPRINTF (buffer, sizeof(buffer),
3714 tree->values.switchVals.swNum);
3716 falseLabel = newiTempLabel (buffer);
3718 /* Build the list of labels for the jump table. */
3720 t = (int) floatFromVal (vch);
3721 for (i=min; i<=max; i++)
3725 /* Explicit case: make a new label for it. */
3726 SNPRINTF (buffer, sizeof(buffer),
3728 tree->values.switchVals.swNum,
3730 addSet (&labels, newiTempLabel (buffer));
3733 t = (int) floatFromVal (vch);
3737 /* Implicit case: use the default label. */
3738 addSet (&labels, falseLabel);
3742 /* first we rule out the boundary conditions */
3743 /* if only optimization says so */
3746 sym_link *cetype = getSpec (operandType (cond));
3747 /* no need to check the lower bound if
3748 the condition is unsigned & minimum value is zero */
3749 if (!(min == 0 && IS_UNSIGNED (cetype)))
3751 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3752 ic = newiCodeCondition (boundary, falseLabel, NULL);
3756 /* now for upper bounds */
3757 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3758 ic = newiCodeCondition (boundary, falseLabel, NULL);
3762 /* if the min is not zero then we no make it zero */
3765 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3766 if (!IS_LITERAL(getSpec(operandType(cond))))
3767 setOperandType (cond, UCHARTYPE);
3770 /* now create the jumptable */
3771 ic = newiCode (JUMPTABLE, NULL, NULL);
3772 IC_JTCOND (ic) = cond;
3773 IC_JTLABELS (ic) = labels;
3778 /*-----------------------------------------------------------------*/
3779 /* geniCodeSwitch - changes a switch to a if statement */
3780 /*-----------------------------------------------------------------*/
3782 geniCodeSwitch (ast * tree,int lvl)
3785 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3786 value *caseVals = tree->values.switchVals.swVals;
3787 symbol *trueLabel, *falseLabel;
3789 /* If the condition is a literal, then just jump to the */
3790 /* appropriate case label. */
3791 if (IS_LITERAL(getSpec(operandType(cond))))
3793 int switchVal, caseVal;
3795 switchVal = (int) floatFromVal (cond->operand.valOperand);
3798 caseVal = (int) floatFromVal (caseVals);
3799 if (caseVal == switchVal)
3801 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3802 tree->values.switchVals.swNum, caseVal);
3803 trueLabel = newiTempLabel (buffer);
3804 geniCodeGoto (trueLabel);
3807 caseVals = caseVals->next;
3809 goto defaultOrBreak;
3812 /* If cond is volatile, it might change while we are trying to */
3813 /* find the matching case. To avoid this possibility, make a */
3814 /* non-volatile copy to use instead. */
3815 if (IS_OP_VOLATILE (cond))
3820 newcond = newiTempOperand (operandType (cond), TRUE);
3821 newcond->isvolatile = 0;
3822 ic = newiCode ('=', NULL, cond);
3823 IC_RESULT (ic) = newcond;
3828 /* if we can make this a jump table */
3829 if (geniCodeJumpTable (cond, caseVals, tree))
3830 goto jumpTable; /* no need for the comparison */
3832 /* for the cases defined do */
3836 operand *compare = geniCodeLogic (cond,
3837 operandFromValue (caseVals),
3840 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3841 tree->values.switchVals.swNum,
3842 (int) floatFromVal (caseVals));
3843 trueLabel = newiTempLabel (buffer);
3845 ic = newiCodeCondition (compare, trueLabel, NULL);
3847 caseVals = caseVals->next;
3852 /* if default is present then goto break else break */
3853 if (tree->values.switchVals.swDefault)
3855 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3859 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3862 falseLabel = newiTempLabel (buffer);
3863 geniCodeGoto (falseLabel);
3866 ast2iCode (tree->right,lvl+1);
3869 /*-----------------------------------------------------------------*/
3870 /* geniCodeInline - intermediate code for inline assembler */
3871 /*-----------------------------------------------------------------*/
3873 geniCodeInline (ast * tree)
3877 ic = newiCode (INLINEASM, NULL, NULL);
3878 IC_INLINE (ic) = tree->values.inlineasm;
3882 /*-----------------------------------------------------------------*/
3883 /* geniCodeArrayInit - intermediate code for array initializer */
3884 /*-----------------------------------------------------------------*/
3886 geniCodeArrayInit (ast * tree, operand *array)
3890 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3891 ic = newiCode (ARRAYINIT, array, NULL);
3892 IC_ARRAYILIST (ic) = tree->values.constlist;
3894 operand *left=newOperand(), *right=newOperand();
3895 left->type=right->type=SYMBOL;
3896 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3897 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3898 ic = newiCode (ARRAYINIT, left, right);
3903 /*-----------------------------------------------------------------*/
3904 /* geniCodeCritical - intermediate code for a critical statement */
3905 /*-----------------------------------------------------------------*/
3907 geniCodeCritical (ast *tree, int lvl)
3913 if (!options.stackAuto)
3915 type = newLink(SPECIFIER);
3916 SPEC_VOLATILE(type) = 1;
3917 SPEC_NOUN(type) = V_BIT;
3918 SPEC_SCLS(type) = S_BIT;
3919 SPEC_BLEN(type) = 1;
3920 SPEC_BSTR(type) = 0;
3921 op = newiTempOperand(type, 1);
3924 /* If op is NULL, the original interrupt state will saved on */
3925 /* the stack. Otherwise, it will be saved in op. */
3927 /* Generate a save of the current interrupt state & disable */
3928 ic = newiCode (CRITICAL, NULL, NULL);
3929 IC_RESULT (ic) = op;
3932 /* Generate the critical code sequence */
3933 if (tree->left && tree->left->type == EX_VALUE)
3934 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3936 ast2iCode (tree->left,lvl+1);
3938 /* Generate a restore of the original interrupt state */
3939 ic = newiCode (ENDCRITICAL, NULL, op);
3943 /*-----------------------------------------------------------------*/
3944 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3945 /* particular case. Ie : assigning or dereferencing array or ptr */
3946 /*-----------------------------------------------------------------*/
3947 set * lvaluereqSet = NULL;
3948 typedef struct lvalItem
3955 /*-----------------------------------------------------------------*/
3956 /* addLvaluereq - add a flag for lvalreq for current ast level */
3957 /*-----------------------------------------------------------------*/
3958 void addLvaluereq(int lvl)
3960 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3963 addSetHead(&lvaluereqSet,lpItem);
3966 /*-----------------------------------------------------------------*/
3967 /* delLvaluereq - del a flag for lvalreq for current ast level */
3968 /*-----------------------------------------------------------------*/
3972 lpItem = getSet(&lvaluereqSet);
3973 if(lpItem) Safe_free(lpItem);
3975 /*-----------------------------------------------------------------*/
3976 /* clearLvaluereq - clear lvalreq flag */
3977 /*-----------------------------------------------------------------*/
3978 void clearLvaluereq()
3981 lpItem = peekSet(lvaluereqSet);
3982 if(lpItem) lpItem->req = 0;
3984 /*-----------------------------------------------------------------*/
3985 /* getLvaluereq - get the last lvalreq level */
3986 /*-----------------------------------------------------------------*/
3987 int getLvaluereqLvl()
3990 lpItem = peekSet(lvaluereqSet);
3991 if(lpItem) return lpItem->lvl;
3994 /*-----------------------------------------------------------------*/
3995 /* isLvaluereq - is lvalreq valid for this level ? */
3996 /*-----------------------------------------------------------------*/
3997 int isLvaluereq(int lvl)
4000 lpItem = peekSet(lvaluereqSet);
4001 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
4005 /*-----------------------------------------------------------------*/
4006 /* ast2iCode - creates an icodeList from an ast */
4007 /*-----------------------------------------------------------------*/
4009 ast2iCode (ast * tree,int lvl)
4011 operand *left = NULL;
4012 operand *right = NULL;
4016 /* set the global variables for filename & line number */
4018 filename = tree->filename;
4020 lineno = tree->lineno;
4022 block = tree->block;
4024 scopeLevel = tree->level;
4026 seqPoint = tree->seqPoint;
4028 if (tree->type == EX_VALUE)
4029 return operandFromValue (tree->opval.val);
4031 if (tree->type == EX_LINK)
4032 return operandFromLink (tree->opval.lnk);
4034 /* if we find a nullop */
4035 if (tree->type == EX_OP &&
4036 (tree->opval.op == NULLOP ||
4037 tree->opval.op == BLOCK))
4039 if (tree->left && tree->left->type == EX_VALUE)
4040 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4042 ast2iCode (tree->left,lvl+1);
4043 if (tree->right && tree->right->type == EX_VALUE)
4044 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4046 ast2iCode (tree->right,lvl+1);
4050 /* special cases for not evaluating */
4051 if (tree->opval.op != ':' &&
4052 tree->opval.op != '?' &&
4053 tree->opval.op != CALL &&
4054 tree->opval.op != IFX &&
4055 tree->opval.op != AND_OP &&
4056 tree->opval.op != OR_OP &&
4057 tree->opval.op != LABEL &&
4058 tree->opval.op != GOTO &&
4059 tree->opval.op != SWITCH &&
4060 tree->opval.op != FUNCTION &&
4061 tree->opval.op != INLINEASM &&
4062 tree->opval.op != CRITICAL)
4065 if (IS_ASSIGN_OP (tree->opval.op) ||
4066 IS_DEREF_OP (tree) ||
4067 (tree->opval.op == '&' && !tree->right) ||
4068 tree->opval.op == PTR_OP)
4071 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4072 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4075 left = operandFromAst (tree->left,lvl);
4077 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4078 left = geniCodeRValue (left, TRUE);
4082 left = operandFromAst (tree->left,lvl);
4084 if (tree->opval.op == INC_OP ||
4085 tree->opval.op == DEC_OP)
4088 right = operandFromAst (tree->right,lvl);
4093 right = operandFromAst (tree->right,lvl);
4097 /* now depending on the type of operand */
4098 /* this will be a biggy */
4099 switch (tree->opval.op)
4102 case '[': /* array operation */
4104 //sym_link *ltype = operandType (left);
4105 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4106 left = geniCodeRValue (left, FALSE);
4107 right = geniCodeRValue (right, TRUE);
4110 return geniCodeArray (left, right,lvl);
4112 case '.': /* structure dereference */
4113 if (IS_PTR (operandType (left)))
4114 left = geniCodeRValue (left, TRUE);
4116 left = geniCodeRValue (left, FALSE);
4118 return geniCodeStruct (left, right, tree->lvalue);
4120 case PTR_OP: /* structure pointer dereference */
4123 pType = operandType (left);
4124 left = geniCodeRValue (left, TRUE);
4126 setOClass (pType, getSpec (operandType (left)));
4129 return geniCodeStruct (left, right, tree->lvalue);
4131 case INC_OP: /* increment operator */
4133 return geniCodePostInc (left);
4135 return geniCodePreInc (right, tree->lvalue);
4137 case DEC_OP: /* decrement operator */
4139 return geniCodePostDec (left);
4141 return geniCodePreDec (right, tree->lvalue);
4143 case '&': /* bitwise and or address of operator */
4145 { /* this is a bitwise operator */
4146 left = geniCodeRValue (left, FALSE);
4147 right = geniCodeRValue (right, FALSE);
4148 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4151 return geniCodeAddressOf (left);
4153 case '|': /* bitwise or & xor */
4155 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4156 geniCodeRValue (right, FALSE),
4161 return geniCodeDivision (geniCodeRValue (left, FALSE),
4162 geniCodeRValue (right, FALSE),
4163 getResultTypeFromType (tree->ftype));
4166 return geniCodeModulus (geniCodeRValue (left, FALSE),
4167 geniCodeRValue (right, FALSE),
4168 getResultTypeFromType (tree->ftype));
4171 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4172 geniCodeRValue (right, FALSE),
4173 getResultTypeFromType (tree->ftype));
4175 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4179 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4180 geniCodeRValue (right, FALSE),
4181 getResultTypeFromType (tree->ftype));
4183 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4187 return geniCodeAdd (geniCodeRValue (left, FALSE),
4188 geniCodeRValue (right, FALSE),
4189 getResultTypeFromType (tree->ftype),
4192 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4195 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4196 geniCodeRValue (right, FALSE),
4197 getResultTypeFromType (tree->ftype));
4200 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4201 geniCodeRValue (right, FALSE));
4203 #if 0 // this indeed needs a second thought
4207 // let's keep this simple: get the rvalue we need
4208 op=geniCodeRValue (right, FALSE);
4209 // now cast it to whatever we want
4210 op=geniCodeCast (operandType(left), op, FALSE);
4211 // if this is going to be used as an lvalue, make it so
4217 #else // bug #604575, is it a bug ????
4218 return geniCodeCast (operandType (left),
4219 geniCodeRValue (right, FALSE), FALSE);
4224 sym_link *ltype = operandType (left);
4225 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4226 if ((SPEC_NOUN(ltype) == V_CHAR) && IS_UNSIGNED(ltype))
4228 setOperandType (op, INTTYPE);
4235 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4240 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4241 setOperandType (op, UCHARTYPE);
4246 return geniCodeLogicAndOr (tree, lvl);
4253 /* different compilers (even different gccs) evaluate
4254 the two calls in a different order. to get the same
4255 result on all machines we've to specify a clear sequence.
4256 return geniCodeLogic (geniCodeRValue (left, FALSE),
4257 geniCodeRValue (right, FALSE),
4261 operand *leftOp, *rightOp;
4263 leftOp = geniCodeRValue (left , FALSE);
4264 rightOp = geniCodeRValue (right, FALSE);
4266 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4269 return geniCodeConditional (tree,lvl);
4272 return operandFromLit (getSize (tree->right->ftype));
4276 sym_link *rtype = operandType (right);
4277 sym_link *ltype = operandType (left);
4278 if (IS_PTR (rtype) && IS_ITEMP (right)
4279 && right->isaddr && compareType (rtype->next, ltype) == 1)
4280 right = geniCodeRValue (right, TRUE);
4282 right = geniCodeRValue (right, FALSE);
4284 geniCodeAssign (left, right, 0, 1);
4289 geniCodeAssign (left,
4290 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4292 geniCodeRValue (right, FALSE),
4293 getResultTypeFromType (tree->ftype)),
4298 geniCodeAssign (left,
4299 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4301 geniCodeRValue (right, FALSE),
4302 getResultTypeFromType (tree->ftype)),
4306 geniCodeAssign (left,
4307 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4309 geniCodeRValue (right, FALSE),
4310 getResultTypeFromType (tree->ftype)),
4314 sym_link *rtype = operandType (right);
4315 sym_link *ltype = operandType (left);
4316 if (IS_PTR (rtype) && IS_ITEMP (right)
4317 && right->isaddr && compareType (rtype->next, ltype) == 1)
4318 right = geniCodeRValue (right, TRUE);
4320 right = geniCodeRValue (right, FALSE);
4323 return geniCodeAssign (left,
4324 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4327 getResultTypeFromType (tree->ftype),
4333 sym_link *rtype = operandType (right);
4334 sym_link *ltype = operandType (left);
4335 if (IS_PTR (rtype) && IS_ITEMP (right)
4336 && right->isaddr && compareType (rtype->next, ltype) == 1)
4338 right = geniCodeRValue (right, TRUE);
4342 right = geniCodeRValue (right, FALSE);
4345 geniCodeAssign (left,
4346 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4349 getResultTypeFromType (tree->ftype)),
4354 geniCodeAssign (left,
4355 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4357 geniCodeRValue (right, FALSE),
4358 getResultTypeFromType (tree->ftype)),
4362 geniCodeAssign (left,
4363 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4365 geniCodeRValue (right, FALSE)), 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);
4384 geniCodeAssign (left,
4385 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4387 geniCodeRValue (right, FALSE),
4389 operandType (left)), 0, 1);
4391 return geniCodeRValue (right, FALSE);
4394 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4397 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4398 return ast2iCode (tree->right,lvl+1);
4401 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4402 return ast2iCode (tree->right,lvl+1);
4405 geniCodeFunctionBody (tree,lvl);
4409 geniCodeReturn (right);
4413 geniCodeIfx (tree,lvl);
4417 geniCodeSwitch (tree,lvl);
4421 geniCodeInline (tree);
4425 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4429 geniCodeCritical (tree, lvl);
4435 /*-----------------------------------------------------------------*/
4436 /* reverseICChain - gets from the list and creates a linkedlist */
4437 /*-----------------------------------------------------------------*/
4444 while ((loop = getSet (&iCodeChain)))
4456 /*-----------------------------------------------------------------*/
4457 /* iCodeFromAst - given an ast will convert it to iCode */
4458 /*-----------------------------------------------------------------*/
4460 iCodeFromAst (ast * tree)
4462 returnLabel = newiTempLabel ("_return");
4463 entryLabel = newiTempLabel ("_entry");
4465 return reverseiCChain ();
4468 static const char *opTypeToStr(OPTYPE op)
4472 case SYMBOL: return "symbol";
4473 case VALUE: return "value";
4474 case TYPE: return "type";
4476 return "undefined type";
4480 operand *validateOpType(operand *op,
4487 if (op && op->type == type)
4492 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4493 " expected %s, got %s\n",
4494 macro, args, file, line,
4495 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4497 return op; // never reached, makes compiler happy.