1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 /*-----------------------------------------------------------------*/
30 /* global variables */
32 set *iCodeChain = NULL;
43 symbol *returnLabel; /* function return label */
44 symbol *entryLabel; /* function entry label */
46 /*-----------------------------------------------------------------*/
47 /* forward definition of some functions */
48 operand *geniCodeAssign (operand *, operand *, int, int);
49 static operand *geniCodeArray (operand *, operand *,int);
50 static operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
54 void setOClass (sym_link * ptr, sym_link * spec);
55 static operand *geniCodeCast (sym_link *, operand *, bool);
57 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
58 /* forward definition of ic print functions */
59 PRINTFUNC (picGetValueAtAddr);
60 PRINTFUNC (picSetValueAtAddr);
61 PRINTFUNC (picAddrOf);
62 PRINTFUNC (picGeneric);
63 PRINTFUNC (picGenericOne);
65 PRINTFUNC (picAssign);
69 PRINTFUNC (picJumpTable);
70 PRINTFUNC (picInline);
71 PRINTFUNC (picReceive);
72 PRINTFUNC (picDummyRead);
73 PRINTFUNC (picCritical);
74 PRINTFUNC (picEndCritical);
76 iCodeTable codeTable[] =
78 {'!', "not", picGenericOne, NULL},
79 {'~', "~", picGenericOne, NULL},
80 {RRC, "rrc", picGenericOne, NULL},
81 {RLC, "rlc", picGenericOne, NULL},
82 {GETHBIT, "ghbit", picGenericOne, NULL},
83 {GETABIT, "gabit", picGenericOne, NULL},
84 {GETBYTE, "gbyte", picGenericOne, NULL},
85 {GETWORD, "gword", picGenericOne, NULL},
86 {UNARYMINUS, "-", picGenericOne, NULL},
87 {IPUSH, "push", picGenericOne, NULL},
88 {IPOP, "pop", picGenericOne, NULL},
89 {CALL, "call", picGenericOne, NULL},
90 {PCALL, "pcall", picGenericOne, NULL},
91 {FUNCTION, "proc", picGenericOne, NULL},
92 {ENDFUNCTION, "eproc", picGenericOne, NULL},
93 {RETURN, "ret", picGenericOne, NULL},
94 {'+', "+", picGeneric, NULL},
95 {'-', "-", picGeneric, NULL},
96 {'*', "*", picGeneric, NULL},
97 {'/', "/", picGeneric, NULL},
98 {'%', "%", picGeneric, NULL},
99 {'>', ">", picGeneric, NULL},
100 {'<', "<", picGeneric, NULL},
101 {LE_OP, "<=", picGeneric, NULL},
102 {GE_OP, ">=", picGeneric, NULL},
103 {EQ_OP, "==", picGeneric, NULL},
104 {NE_OP, "!=", picGeneric, NULL},
105 {AND_OP, "&&", picGeneric, NULL},
106 {OR_OP, "||", picGeneric, NULL},
107 {'^', "^", picGeneric, NULL},
108 {'|', "|", picGeneric, NULL},
109 {BITWISEAND, "&", picGeneric, NULL},
110 {LEFT_OP, "<<", picGeneric, NULL},
111 {RIGHT_OP, ">>", picGeneric, NULL},
112 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
113 {ADDRESS_OF, "&", picAddrOf, NULL},
114 {CAST, "<>", picCast, NULL},
115 {'=', ":=", picAssign, NULL},
116 {LABEL, "", picLabel, NULL},
117 {GOTO, "", picGoto, NULL},
118 {JUMPTABLE, "jtab", picJumpTable, NULL},
119 {IFX, "if", picIfx, NULL},
120 {INLINEASM, "", picInline, NULL},
121 {RECEIVE, "recv", picReceive, NULL},
122 {SEND, "send", picGenericOne, NULL},
123 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
124 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
125 {CRITICAL, "critical_start", picCritical, NULL},
126 {ENDCRITICAL, "critical_end", picEndCritical, NULL},
127 {SWAP, "swap", picGenericOne, NULL}
130 /*-----------------------------------------------------------------*/
131 /* checkConstantRange: check a constant against the type */
132 /*-----------------------------------------------------------------*/
135 /* pedantic=0: allmost anything is allowed as long as the absolute
136 value is within the bit range of the type, and -1 is treated as
137 0xf..f for unsigned types (e.g. in assign)
138 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
139 pedantic>1: "char c=200" is not allowed (evaluates to -56)
142 void checkConstantRange(sym_link *ltype, value *val, char *msg,
149 max = pow ((double)2.0, (double)bitsForType(ltype));
151 if (IS_LONG(val->type)) {
152 if (IS_UNSIGNED(val->type)) {
153 v=SPEC_CVAL(val->type).v_ulong;
155 v=SPEC_CVAL(val->type).v_long;
158 if (IS_UNSIGNED(val->type)) {
159 v=SPEC_CVAL(val->type).v_uint;
161 v=SPEC_CVAL(val->type).v_int;
167 // this could be a good idea
168 if (options.pedantic)
172 if (IS_FLOAT(ltype)) {
177 if (IS_FIXED(ltype)) {
182 if (!IS_UNSIGNED(val->type) && v<0) {
184 if (IS_UNSIGNED(ltype) && (pedantic>1)) {
190 // if very pedantic: "char c=200" is not allowed
191 if (pedantic>1 && !IS_UNSIGNED(ltype)) {
192 max = max/2 + negative;
199 #if 0 // temporary disabled, leaving the warning as a reminder
201 SNPRINTF (message, sizeof(message), "for %s %s in %s",
202 IS_UNSIGNED(ltype) ? "unsigned" : "signed",
203 nounName(ltype), msg);
204 werror (W_CONST_RANGE, message);
212 /*-----------------------------------------------------------------*/
213 /* operandName - returns the name of the operand */
214 /*-----------------------------------------------------------------*/
216 printOperand (operand * op, FILE * file)
233 opetype = getSpec (operandType (op));
234 if (IS_FLOAT (opetype))
235 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
236 if (IS_FIXED16X16 (opetype))
237 fprintf (file, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
239 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
240 printTypeChain (operandType (op), file);
247 if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
248 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}" , */
249 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
251 OP_LIVEFROM (op), OP_LIVETO (op),
252 OP_SYMBOL (op)->stack,
253 op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
254 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
255 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
259 printTypeChain (operandType (op), file);
260 if (SPIL_LOC (op) && IS_ITEMP (op))
261 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
266 /* if assigned to registers */
267 if (OP_SYMBOL (op)->nRegs)
269 if (OP_SYMBOL (op)->isspilt)
271 if (!OP_SYMBOL (op)->remat)
272 if (OP_SYMBOL (op)->usl.spillLoc)
273 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
274 OP_SYMBOL (op)->usl.spillLoc->rname :
275 OP_SYMBOL (op)->usl.spillLoc->name));
277 fprintf (file, "[err]");
279 fprintf (file, "[remat]");
285 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
286 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
290 //#else /* } else { */
292 /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
293 fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
295 if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
297 fprintf (file, "[lr%d:%d so:%d]",
298 OP_LIVEFROM (op), OP_LIVETO (op),
299 OP_SYMBOL (op)->stack);
302 if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
305 printTypeChain (operandType (op), file);
306 if (SPIL_LOC (op) && IS_ITEMP (op))
307 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
311 /* if assigned to registers */
312 if (OP_SYMBOL (op)->nRegs)
314 if (OP_SYMBOL (op)->isspilt)
316 if (!OP_SYMBOL (op)->remat)
317 if (OP_SYMBOL (op)->usl.spillLoc)
318 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
319 OP_SYMBOL (op)->usl.spillLoc->rname :
320 OP_SYMBOL (op)->usl.spillLoc->name));
322 fprintf (file, "[err]");
324 fprintf (file, "[remat]");
330 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
331 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
341 printTypeChain (op->operand.typeOperand, file);
347 fprintf (file, "\n");
352 /*-----------------------------------------------------------------*/
353 /* print functions */
354 /*-----------------------------------------------------------------*/
355 PRINTFUNC (picGetValueAtAddr)
358 printOperand (IC_RESULT (ic), of);
361 printOperand (IC_LEFT (ic), of);
367 PRINTFUNC (picSetValueAtAddr)
371 printOperand (IC_LEFT (ic), of);
372 fprintf (of, "] = ");
373 printOperand (IC_RIGHT (ic), of);
377 PRINTFUNC (picAddrOf)
380 printOperand (IC_RESULT (ic), of);
381 if (IS_ITEMP (IC_LEFT (ic)))
384 fprintf (of, " = &[");
385 printOperand (IC_LEFT (ic), of);
388 if (IS_ITEMP (IC_LEFT (ic)))
389 fprintf (of, " offsetAdd ");
392 printOperand (IC_RIGHT (ic), of);
394 if (IS_ITEMP (IC_LEFT (ic)))
400 PRINTFUNC (picJumpTable)
405 fprintf (of, "%s\t", s);
406 printOperand (IC_JTCOND (ic), of);
408 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
409 sym = setNextItem (IC_JTLABELS (ic)))
410 fprintf (of, "\t\t\t%s\n", sym->name);
413 PRINTFUNC (picGeneric)
416 printOperand (IC_RESULT (ic), of);
418 printOperand (IC_LEFT (ic), of);
419 fprintf (of, " %s ", s);
420 printOperand (IC_RIGHT (ic), of);
424 PRINTFUNC (picGenericOne)
429 printOperand (IC_RESULT (ic), of);
435 fprintf (of, "%s ", s);
436 printOperand (IC_LEFT (ic), of);
439 if (!IC_RESULT (ic) && !IC_LEFT (ic))
442 if (ic->op == SEND || ic->op == RECEIVE) {
443 fprintf(of,"{argreg = %d}",ic->argreg);
445 if (ic->op == IPUSH) {
446 fprintf(of,"{parmPush = %d}",ic->parmPush);
454 printOperand (IC_RESULT (ic), of);
456 printOperand (IC_LEFT (ic), of);
457 printOperand (IC_RIGHT (ic), of);
462 PRINTFUNC (picAssign)
466 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
469 printOperand (IC_RESULT (ic), of);
471 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
474 fprintf (of, " %s ", s);
475 printOperand (IC_RIGHT (ic), of);
482 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
488 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
495 printOperand (IC_COND (ic), of);
498 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
501 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
503 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
507 PRINTFUNC (picInline)
509 fprintf (of, "%s", IC_INLINE (ic));
512 PRINTFUNC (picReceive)
514 printOperand (IC_RESULT (ic), of);
515 fprintf (of, " = %s ", s);
516 printOperand (IC_LEFT (ic), of);
520 PRINTFUNC (picDummyRead)
523 fprintf (of, "%s ", s);
524 printOperand (IC_RIGHT (ic), of);
528 PRINTFUNC (picCritical)
532 printOperand (IC_RESULT (ic), of);
534 fprintf (of, "(stack)");
535 fprintf (of, " = %s ", s);
539 PRINTFUNC (picEndCritical)
542 fprintf (of, "%s = ", s);
544 printOperand (IC_RIGHT (ic), of);
546 fprintf (of, "(stack)");
550 /*-----------------------------------------------------------------*/
551 /* piCode - prints one iCode */
552 /*-----------------------------------------------------------------*/
554 piCode (void *item, FILE * of)
562 icTab = getTableEntry (ic->op);
563 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
564 ic->filename, ic->lineno,
565 ic->seq, ic->key, ic->depth, ic->supportRtn);
566 icTab->iCodePrint (of, ic, icTab->printName);
572 printiCChain(ic,stdout);
574 /*-----------------------------------------------------------------*/
575 /* printiCChain - prints intermediate code for humans */
576 /*-----------------------------------------------------------------*/
578 printiCChain (iCode * icChain, FILE * of)
585 for (loop = icChain; loop; loop = loop->next)
587 if ((icTab = getTableEntry (loop->op)))
589 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
590 loop->filename, loop->lineno,
591 loop->seq, loop->key, loop->depth, loop->supportRtn);
593 icTab->iCodePrint (of, loop, icTab->printName);
599 /*-----------------------------------------------------------------*/
600 /* newOperand - allocate, init & return a new iCode */
601 /*-----------------------------------------------------------------*/
607 op = Safe_alloc ( sizeof (operand));
613 /*-----------------------------------------------------------------*/
614 /* newiCode - create and return a new iCode entry initialised */
615 /*-----------------------------------------------------------------*/
617 newiCode (int op, operand * left, operand * right)
621 ic = Safe_alloc ( sizeof (iCode));
623 ic->seqPoint = seqPoint;
625 ic->filename = filename;
627 ic->level = scopeLevel;
629 ic->key = iCodeKey++;
631 IC_RIGHT (ic) = right;
636 /*-----------------------------------------------------------------*/
637 /* newiCode for conditional statements */
638 /*-----------------------------------------------------------------*/
640 newiCodeCondition (operand * condition,
646 if (IS_VOID(operandType(condition))) {
647 werror(E_VOID_VALUE_USED);
650 ic = newiCode (IFX, NULL, NULL);
651 IC_COND (ic) = condition;
652 IC_TRUE (ic) = trueLabel;
653 IC_FALSE (ic) = falseLabel;
657 /*-----------------------------------------------------------------*/
658 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
659 /*-----------------------------------------------------------------*/
661 newiCodeLabelGoto (int op, symbol * label)
665 ic = newiCode (op, NULL, NULL);
669 IC_RIGHT (ic) = NULL;
670 IC_RESULT (ic) = NULL;
674 /*-----------------------------------------------------------------*/
675 /* newiTemp - allocate & return a newItemp Variable */
676 /*-----------------------------------------------------------------*/
684 SNPRINTF (buffer, sizeof(buffer), "%s", s);
688 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
691 itmp = newSymbol (buffer, 1);
692 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
698 /*-----------------------------------------------------------------*/
699 /* newiTempLabel - creates a temp variable label */
700 /*-----------------------------------------------------------------*/
702 newiTempLabel (char *s)
706 /* check if this already exists */
707 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
712 itmplbl = newSymbol (s, 1);
716 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
717 itmplbl = newSymbol (buffer, 1);
722 itmplbl->key = labelKey++;
723 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
727 /*-----------------------------------------------------------------*/
728 /* newiTempPreheaderLabel - creates a new preheader label */
729 /*-----------------------------------------------------------------*/
731 newiTempPreheaderLabel ()
735 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
736 itmplbl = newSymbol (buffer, 1);
740 itmplbl->key = labelKey++;
741 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
746 /*-----------------------------------------------------------------*/
747 /* initiCode - initialises some iCode related stuff */
748 /*-----------------------------------------------------------------*/
755 /*-----------------------------------------------------------------*/
756 /* copyiCode - make a copy of the iCode given */
757 /*-----------------------------------------------------------------*/
759 copyiCode (iCode * ic)
761 iCode *nic = newiCode (ic->op, NULL, NULL);
763 nic->lineno = ic->lineno;
764 nic->filename = ic->filename;
765 nic->block = ic->block;
766 nic->level = ic->level;
767 nic->parmBytes = ic->parmBytes;
769 /* deal with the special cases first */
773 IC_COND (nic) = operandFromOperand (IC_COND (ic));
774 IC_TRUE (nic) = IC_TRUE (ic);
775 IC_FALSE (nic) = IC_FALSE (ic);
779 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
780 IC_JTLABELS (nic) = IC_JTLABELS (ic);
785 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
786 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
790 IC_INLINE (nic) = IC_INLINE (ic);
794 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
798 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
799 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
800 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
806 /*-----------------------------------------------------------------*/
807 /* getTableEntry - gets the table entry for the given operator */
808 /*-----------------------------------------------------------------*/
810 getTableEntry (int oper)
814 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
815 if (oper == codeTable[i].icode)
816 return &codeTable[i];
821 /*-----------------------------------------------------------------*/
822 /* newiTempOperand - new intermediate temp operand */
823 /*-----------------------------------------------------------------*/
825 newiTempOperand (sym_link * type, char throwType)
828 operand *op = newOperand ();
832 itmp = newiTemp (NULL);
834 etype = getSpec (type);
836 if (IS_LITERAL (etype))
839 /* copy the type information */
841 itmp->etype = getSpec (itmp->type = (throwType ? type :
842 copyLinkChain (type)));
843 if (IS_LITERAL (itmp->etype))
845 SPEC_SCLS (itmp->etype) = S_REGISTER;
846 SPEC_OCLS (itmp->etype) = reg;
849 op->operand.symOperand = itmp;
850 op->key = itmp->key = ++operandKey;
854 /*-----------------------------------------------------------------*/
855 /* operandType - returns the type chain for an operand */
856 /*-----------------------------------------------------------------*/
858 operandType (operand * op)
860 /* depending on type of operand */
865 return op->operand.valOperand->type;
868 return op->operand.symOperand->type;
871 return op->operand.typeOperand;
873 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
874 " operand type not known ");
875 assert (0); /* should never come here */
876 /* Just to keep the compiler happy */
877 return (sym_link *) 0;
881 /*-----------------------------------------------------------------*/
882 /* isParamterToCall - will return 1 if op is a parameter to args */
883 /*-----------------------------------------------------------------*/
885 isParameterToCall (value * args, operand * op)
889 wassert (IS_SYMOP(op));
894 isSymbolEqual (op->operand.symOperand, tval->sym))
901 /*-----------------------------------------------------------------*/
902 /* isOperandGlobal - return 1 if operand is a global variable */
903 /*-----------------------------------------------------------------*/
905 isOperandGlobal (operand * op)
914 (op->operand.symOperand->level == 0 ||
915 IS_STATIC (op->operand.symOperand->etype) ||
916 IS_EXTERN (op->operand.symOperand->etype))
923 /*-----------------------------------------------------------------*/
924 /* isOperandVolatile - return 1 if the operand is volatile */
925 /*-----------------------------------------------------------------*/
927 isOperandVolatile (operand * op, bool chkTemp)
932 if (IS_ITEMP (op) && !chkTemp)
935 opetype = getSpec (optype = operandType (op));
937 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
940 if (IS_VOLATILE (opetype))
945 /*-----------------------------------------------------------------*/
946 /* isOperandLiteral - returns 1 if an operand contains a literal */
947 /*-----------------------------------------------------------------*/
949 isOperandLiteral (operand * op)
956 opetype = getSpec (operandType (op));
958 if (IS_LITERAL (opetype))
964 /*-----------------------------------------------------------------*/
965 /* isOperandInFarSpace - will return true if operand is in farSpace */
966 /*-----------------------------------------------------------------*/
968 isOperandInFarSpace (operand * op)
978 if (!IS_TRUE_SYMOP (op))
981 etype = SPIL_LOC (op)->etype;
987 etype = getSpec (operandType (op));
989 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
992 /*------------------------------------------------------------------*/
993 /* isOperandInDirSpace - will return true if operand is in dirSpace */
994 /*------------------------------------------------------------------*/
996 isOperandInDirSpace (operand * op)
1006 if (!IS_TRUE_SYMOP (op))
1009 etype = SPIL_LOC (op)->etype;
1015 etype = getSpec (operandType (op));
1017 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1020 /*--------------------------------------------------------------------*/
1021 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
1022 /*--------------------------------------------------------------------*/
1024 isOperandInCodeSpace (operand * op)
1034 etype = getSpec (operandType (op));
1036 if (!IS_TRUE_SYMOP (op))
1039 etype = SPIL_LOC (op)->etype;
1045 etype = getSpec (operandType (op));
1047 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1050 /*-----------------------------------------------------------------*/
1051 /* isOperandOnStack - will return true if operand is on stack */
1052 /*-----------------------------------------------------------------*/
1054 isOperandOnStack (operand * op)
1064 etype = getSpec (operandType (op));
1065 if (IN_STACK (etype) ||
1066 OP_SYMBOL(op)->onStack ||
1067 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1073 /*-----------------------------------------------------------------*/
1074 /* isOclsExpensive - will return true if accesses to an output */
1075 /* storage class are expensive */
1076 /*-----------------------------------------------------------------*/
1078 isOclsExpensive (struct memmap *oclass)
1080 if (port->oclsExpense)
1081 return port->oclsExpense (oclass) > 0;
1083 /* In the absence of port specific guidance, assume only */
1084 /* farspace is expensive. */
1085 return IN_FARSPACE (oclass);
1088 /*-----------------------------------------------------------------*/
1089 /* isiCodeInFunctionCall - return TRUE if an iCode is between a */
1090 /* CALL/PCALL and the first IPUSH/SEND associated with the call */
1091 /*-----------------------------------------------------------------*/
1093 isiCodeInFunctionCall (iCode * ic)
1097 /* Find the next CALL/PCALL */
1100 if (lic->op == CALL || lic->op == PCALL)
1108 /* A function call was found. Scan backwards and see if an */
1109 /* IPUSH or SEND is encountered */
1112 if (lic != ic && (ic->op == CALL || ic->op == PCALL))
1114 if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
1122 /*-----------------------------------------------------------------*/
1123 /* operandLitValue - literal value of an operand */
1124 /*-----------------------------------------------------------------*/
1126 operandLitValue (operand * op)
1128 assert (isOperandLiteral (op));
1130 return floatFromVal (op->operand.valOperand);
1133 /*-----------------------------------------------------------------*/
1134 /* getBuiltInParms - returns parameters to a builtin functions */
1135 /*-----------------------------------------------------------------*/
1136 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1141 /* builtin functions uses only SEND for parameters */
1142 while (ic->op != CALL) {
1143 assert(ic->op == SEND && ic->builtinSEND);
1144 ic->generated = 1; /* mark the icode as generated */
1145 parms[*pcount] = IC_LEFT(ic);
1151 /* make sure this is a builtin function call */
1152 assert(IS_SYMOP(IC_LEFT(ic)));
1153 ftype = operandType(IC_LEFT(ic));
1154 assert(IFFUNC_ISBUILTIN(ftype));
1158 /*-----------------------------------------------------------------*/
1159 /* operandOperation - performs operations on operands */
1160 /*-----------------------------------------------------------------*/
1162 operandOperation (operand * left, operand * right,
1163 int op, sym_link * type)
1165 sym_link *let , *ret=NULL;
1166 operand *retval = (operand *) 0;
1168 assert (isOperandLiteral (left));
1169 let = getSpec(operandType(left));
1171 assert (isOperandLiteral (right));
1172 ret = getSpec(operandType(right));
1178 retval = operandFromValue (valCastLiteral (type,
1179 operandLitValue (left) +
1180 operandLitValue (right)));
1183 retval = operandFromValue (valCastLiteral (type,
1184 operandLitValue (left) -
1185 operandLitValue (right)));
1189 retval = operandFromValue (valCastLiteral (type,
1190 operandLitValue (left) *
1191 operandLitValue (right)));
1192 This could be all we've to do, but with gcc we've to take care about
1193 overflows. Two examples:
1194 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1195 significant bits are lost (52 in fraction, 63 bits would be
1196 necessary to keep full precision).
1197 If the resulting double value is greater than ULONG_MAX (resp.
1198 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1201 /* if it is not a specifier then we can assume that */
1202 /* it will be an unsigned long */
1203 if (IS_INT (type) ||
1206 /* long is handled here, because it can overflow with double */
1207 if (IS_LONG (type) ||
1209 /* signed and unsigned mul are the same, as long as the precision
1210 of the result isn't bigger than the precision of the operands. */
1211 retval = operandFromValue (valCastLiteral (type,
1212 (TYPE_UDWORD) operandLitValue (left) *
1213 (TYPE_UDWORD) operandLitValue (right)));
1214 else if (IS_UNSIGNED (type)) /* unsigned int */
1216 /* unsigned int is handled here in order to detect overflow */
1217 TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
1218 (TYPE_UWORD) operandLitValue (right);
1220 retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
1221 if (ul != (TYPE_UWORD) ul)
1224 else /* signed int */
1226 /* signed int is handled here in order to detect overflow */
1227 TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
1228 (TYPE_WORD) operandLitValue (right);
1230 retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
1231 if (l != (TYPE_WORD) l)
1236 /* all others go here: */
1237 retval = operandFromValue (valCastLiteral (type,
1238 operandLitValue (left) *
1239 operandLitValue (right)));
1242 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1244 werror (E_DIVIDE_BY_ZERO);
1250 if (IS_UNSIGNED (type))
1252 SPEC_USIGN (let) = 1;
1253 SPEC_USIGN (ret) = 1;
1254 retval = operandFromValue (valCastLiteral (type,
1255 (TYPE_UDWORD) operandLitValue (left) /
1256 (TYPE_UDWORD) operandLitValue (right)));
1260 retval = operandFromValue (valCastLiteral (type,
1261 operandLitValue (left) /
1262 operandLitValue (right)));
1267 if ((TYPE_UDWORD) operandLitValue (right) == 0)
1269 werror (E_DIVIDE_BY_ZERO);
1274 if (IS_UNSIGNED (type))
1275 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1276 (TYPE_UDWORD) operandLitValue (right));
1278 retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1279 (TYPE_DWORD) operandLitValue (right));
1283 /* The number of left shifts is always unsigned. Signed doesn't make
1284 sense here. Shifting by a negative number is impossible. */
1285 retval = operandFromValue (valCastLiteral (type,
1286 ((TYPE_UDWORD) operandLitValue (left) <<
1287 (TYPE_UDWORD) operandLitValue (right))));
1290 /* The number of right shifts is always unsigned. Signed doesn't make
1291 sense here. Shifting by a negative number is impossible. */
1292 if (IS_UNSIGNED(let))
1293 /* unsigned: logic shift right */
1294 retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1295 (TYPE_UDWORD) operandLitValue (right));
1297 /* signed: arithmetic shift right */
1298 retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1299 (TYPE_UDWORD) operandLitValue (right));
1302 if (IS_FLOAT (let) ||
1305 retval = operandFromLit (operandLitValue (left) ==
1306 operandLitValue (right));
1309 if (IS_FIXED16X16 (let) ||
1310 IS_FIXED16X16 (ret))
1312 retval = operandFromLit (operandLitValue (left) ==
1313 operandLitValue (right));
1317 /* this op doesn't care about signedness */
1320 l = (TYPE_UDWORD) operandLitValue (left);
1321 r = (TYPE_UDWORD) operandLitValue (right);
1322 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1323 neccessary to strip them to 16 bit.
1324 Literals are reduced to their cheapest type, therefore left and
1325 right might have different types. It's neccessary to find a
1326 common type: int (used for char too) or long */
1327 if (!IS_LONG (let) &&
1333 retval = operandFromLit (l == r);
1337 retval = operandFromLit (operandLitValue (left) <
1338 operandLitValue (right));
1341 retval = operandFromLit (operandLitValue (left) <=
1342 operandLitValue (right));
1345 retval = operandFromLit (operandLitValue (left) !=
1346 operandLitValue (right));
1349 retval = operandFromLit (operandLitValue (left) >
1350 operandLitValue (right));
1353 retval = operandFromLit (operandLitValue (left) >=
1354 operandLitValue (right));
1357 retval = operandFromValue (valCastLiteral (type,
1358 (TYPE_UDWORD)operandLitValue(left) &
1359 (TYPE_UDWORD)operandLitValue(right)));
1362 retval = operandFromValue (valCastLiteral (type,
1363 (TYPE_UDWORD)operandLitValue(left) |
1364 (TYPE_UDWORD)operandLitValue(right)));
1367 retval = operandFromValue (valCastLiteral (type,
1368 (TYPE_UDWORD)operandLitValue(left) ^
1369 (TYPE_UDWORD)operandLitValue(right)));
1372 retval = operandFromLit (operandLitValue (left) &&
1373 operandLitValue (right));
1376 retval = operandFromLit (operandLitValue (left) ||
1377 operandLitValue (right));
1381 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1383 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1389 TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1391 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1397 retval = operandFromValue (valCastLiteral (type,
1398 -1 * operandLitValue (left)));
1402 retval = operandFromValue (valCastLiteral (type,
1404 operandLitValue (left))));
1408 retval = operandFromLit (!operandLitValue (left));
1412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413 " operandOperation invalid operator ");
1421 /*-----------------------------------------------------------------*/
1422 /* isOperandEqual - compares two operand & return 1 if they r = */
1423 /*-----------------------------------------------------------------*/
1425 isOperandEqual (operand * left, operand * right)
1427 /* if the pointers are equal then they are equal */
1431 /* if either of them null then false */
1432 if (!left || !right)
1435 if (left->type != right->type)
1438 if (IS_SYMOP (left) && IS_SYMOP (right))
1439 return left->key == right->key;
1441 /* if types are the same */
1445 return isSymbolEqual (left->operand.symOperand,
1446 right->operand.symOperand);
1448 return (compareType (left->operand.valOperand->type,
1449 right->operand.valOperand->type) &&
1450 (floatFromVal (left->operand.valOperand) ==
1451 floatFromVal (right->operand.valOperand)));
1453 if (compareType (left->operand.typeOperand,
1454 right->operand.typeOperand) == 1)
1461 /*-------------------------------------------------------------------*/
1462 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1463 /*-------------------------------------------------------------------*/
1465 isiCodeEqual (iCode * left, iCode * right)
1467 /* if the same pointer */
1471 /* if either of them null */
1472 if (!left || !right)
1475 /* if operand are the same */
1476 if (left->op == right->op)
1479 /* compare all the elements depending on type */
1480 if (left->op != IFX)
1482 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1484 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1490 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1492 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1494 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1503 /*-----------------------------------------------------------------*/
1504 /* newiTempFromOp - create a temp Operand with same attributes */
1505 /*-----------------------------------------------------------------*/
1507 newiTempFromOp (operand * op)
1517 nop = newiTempOperand (operandType (op), TRUE);
1518 nop->isaddr = op->isaddr;
1519 nop->isvolatile = op->isvolatile;
1520 nop->isGlobal = op->isGlobal;
1521 nop->isLiteral = op->isLiteral;
1522 nop->usesDefs = op->usesDefs;
1523 nop->isParm = op->isParm;
1527 /*-----------------------------------------------------------------*/
1528 /* operand from operand - creates an operand holder for the type */
1529 /*-----------------------------------------------------------------*/
1531 operandFromOperand (operand * op)
1537 nop = newOperand ();
1538 nop->type = op->type;
1539 nop->isaddr = op->isaddr;
1541 nop->isvolatile = op->isvolatile;
1542 nop->isGlobal = op->isGlobal;
1543 nop->isLiteral = op->isLiteral;
1544 nop->usesDefs = op->usesDefs;
1545 nop->isParm = op->isParm;
1550 nop->operand.symOperand = op->operand.symOperand;
1553 nop->operand.valOperand = op->operand.valOperand;
1556 nop->operand.typeOperand = op->operand.typeOperand;
1563 /*-----------------------------------------------------------------*/
1564 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1565 /*-----------------------------------------------------------------*/
1567 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1569 operand *nop = operandFromOperand (op);
1571 if (nop->type == SYMBOL)
1573 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1574 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1580 /*-----------------------------------------------------------------*/
1581 /* operandFromSymbol - creates an operand from a symbol */
1582 /*-----------------------------------------------------------------*/
1584 operandFromSymbol (symbol * sym)
1589 /* if the symbol's type is a literal */
1590 /* then it is an enumerator type */
1591 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1592 return operandFromValue (valFromType (sym->etype));
1595 sym->key = ++operandKey;
1597 /* if this an implicit variable, means struct/union */
1598 /* member so just return it */
1599 if (sym->implicit || IS_FUNC (sym->type))
1603 op->operand.symOperand = sym;
1605 op->isvolatile = isOperandVolatile (op, TRUE);
1606 op->isGlobal = isOperandGlobal (op);
1610 /* under the following conditions create a
1611 register equivalent for a local symbol */
1612 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1613 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1615 (!(options.model == MODEL_FLAT24)) ) &&
1616 options.stackAuto == 0)
1619 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1620 !IS_FUNC (sym->type) && /* not a function */
1621 !sym->_isparm && /* not a parameter */
1622 IS_AUTO (sym) && /* is a local auto variable */
1623 !sym->addrtaken && /* whose address has not been taken */
1624 !sym->reqv && /* does not already have a reg equivalence */
1625 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1626 !sym->islbl && /* not a label */
1627 ok /* farspace check */
1631 /* we will use it after all optimizations
1632 and before liveRange calculation */
1633 sym->reqv = newiTempOperand (sym->type, 0);
1634 sym->reqv->key = sym->key;
1635 OP_SYMBOL (sym->reqv)->prereqv = sym;
1636 OP_SYMBOL (sym->reqv)->key = sym->key;
1637 OP_SYMBOL (sym->reqv)->isreqv = 1;
1638 OP_SYMBOL (sym->reqv)->islocal = 1;
1639 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1640 SPIL_LOC (sym->reqv) = sym;
1643 if (!IS_AGGREGATE (sym->type))
1647 op->operand.symOperand = sym;
1650 op->isvolatile = isOperandVolatile (op, TRUE);
1651 op->isGlobal = isOperandGlobal (op);
1652 op->isPtr = IS_PTR (operandType (op));
1653 op->isParm = sym->_isparm;
1658 /* itemp = &[_symbol] */
1660 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1661 IC_LEFT (ic)->type = SYMBOL;
1662 IC_LEFT (ic)->operand.symOperand = sym;
1663 IC_LEFT (ic)->key = sym->key;
1664 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1665 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1666 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1669 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1670 if (IS_ARRAY (sym->type))
1672 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1673 IC_RESULT (ic)->isaddr = 0;
1676 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1680 return IC_RESULT (ic);
1683 /*-----------------------------------------------------------------*/
1684 /* operandFromValue - creates an operand from value */
1685 /*-----------------------------------------------------------------*/
1687 operandFromValue (value * val)
1691 /* if this is a symbol then do the symbol thing */
1693 return operandFromSymbol (val->sym);
1695 /* this is not a symbol */
1698 op->operand.valOperand = val;
1699 op->isLiteral = isOperandLiteral (op);
1703 /*-----------------------------------------------------------------*/
1704 /* operandFromLink - operand from typeChain */
1705 /*-----------------------------------------------------------------*/
1707 operandFromLink (sym_link * type)
1711 /* operand from sym_link */
1717 op->operand.typeOperand = copyLinkChain (type);
1721 /*-----------------------------------------------------------------*/
1722 /* operandFromLit - makes an operand from a literal value */
1723 /*-----------------------------------------------------------------*/
1725 operandFromLit (double i)
1727 return operandFromValue (valueFromLit (i));
1730 /*-----------------------------------------------------------------*/
1731 /* operandFromAst - creates an operand from an ast */
1732 /*-----------------------------------------------------------------*/
1734 operandFromAst (ast * tree,int lvl)
1740 /* depending on type do */
1744 return ast2iCode (tree,lvl+1);
1748 return operandFromValue (tree->opval.val);
1752 return operandFromLink (tree->opval.lnk);
1759 /* Just to keep the compiler happy */
1760 return (operand *) 0;
1763 /*-----------------------------------------------------------------*/
1764 /* setOperandType - sets the operand's type to the given type */
1765 /*-----------------------------------------------------------------*/
1767 setOperandType (operand * op, sym_link * type)
1769 /* depending on the type of operand */
1774 op->operand.valOperand->etype =
1775 getSpec (op->operand.valOperand->type =
1776 copyLinkChain (type));
1780 if (op->operand.symOperand->isitmp)
1781 op->operand.symOperand->etype =
1782 getSpec (op->operand.symOperand->type =
1783 copyLinkChain (type));
1785 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1786 "attempt to modify type of source");
1790 op->operand.typeOperand = copyLinkChain (type);
1796 /*-----------------------------------------------------------------*/
1797 /* Get size in byte of ptr need to access an array */
1798 /*-----------------------------------------------------------------*/
1800 getArraySizePtr (operand * op)
1802 sym_link *ltype = operandType(op);
1806 int size = getSize(ltype);
1807 return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1812 sym_link *letype = getSpec(ltype);
1813 switch (PTR_TYPE (SPEC_OCLS (letype)))
1825 if (GPTRSIZE > FPTRSIZE)
1826 return (GPTRSIZE-1);
1837 /*-----------------------------------------------------------------*/
1838 /* perform "usual unary conversions" */
1839 /*-----------------------------------------------------------------*/
1842 usualUnaryConversions (operand * op)
1844 if (IS_INTEGRAL (operandType (op)))
1846 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1849 return geniCodeCast (INTTYPE, op, TRUE);
1856 /*-----------------------------------------------------------------*/
1857 /* perform "usual binary conversions" */
1858 /*-----------------------------------------------------------------*/
1861 usualBinaryConversions (operand ** op1, operand ** op2,
1862 RESULT_TYPE resultType, int op)
1865 sym_link *rtype = operandType (*op2);
1866 sym_link *ltype = operandType (*op1);
1868 ctype = computeType (ltype, rtype, resultType, op);
1875 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1877 /* one byte operations: keep signedness for code generator */
1885 *op1 = geniCodeCast (ctype, *op1, TRUE);
1886 *op2 = geniCodeCast (ctype, *op2, TRUE);
1891 /*-----------------------------------------------------------------*/
1892 /* geniCodeValueAtAddress - generate intermeditate code for value */
1894 /*-----------------------------------------------------------------*/
1896 geniCodeRValue (operand * op, bool force)
1899 sym_link *type = operandType (op);
1900 sym_link *etype = getSpec (type);
1902 /* if this is an array & already */
1903 /* an address then return this */
1904 if (IS_AGGREGATE (type) ||
1905 (IS_PTR (type) && !force && !op->isaddr))
1906 return operandFromOperand (op);
1908 /* if this is not an address then must be */
1909 /* rvalue already so return this one */
1913 /* if this is not a temp symbol then */
1914 if (!IS_ITEMP (op) &&
1916 !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1918 op = operandFromOperand (op);
1923 if (IS_SPEC (type) &&
1924 IS_TRUE_SYMOP (op) &&
1925 (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1926 (options.model == MODEL_FLAT24) ))
1928 op = operandFromOperand (op);
1933 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1934 if (IS_PTR (type) && op->isaddr && force)
1937 type = copyLinkChain (type);
1939 IC_RESULT (ic) = newiTempOperand (type, 1);
1940 IC_RESULT (ic)->isaddr = 0;
1942 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1946 return IC_RESULT (ic);
1949 /*-----------------------------------------------------------------*/
1950 /* geniCodeCast - changes the value from one type to another */
1951 /*-----------------------------------------------------------------*/
1953 geniCodeCast (sym_link * type, operand * op, bool implicit)
1957 sym_link *opetype = getSpec (optype = operandType (op));
1961 /* one of them has size zero then error */
1962 if (IS_VOID (optype))
1964 werror (E_CAST_ZERO);
1968 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1970 geniCodeArray2Ptr (op);
1974 /* if the operand is already the desired type then do nothing */
1975 if (compareType (type, optype) == 1)
1978 /* if this is a literal then just change the type & return */
1979 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1981 return operandFromValue (valCastLiteral (type,
1982 operandLitValue (op)));
1985 /* if casting to/from pointers, do some checking */
1986 if (IS_PTR(type)) { // to a pointer
1987 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1988 if (IS_INTEGRAL(optype)) {
1989 // maybe this is NULL, than it's ok.
1990 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1991 if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1992 // no way to set the storage
1993 if (IS_LITERAL(optype)) {
1994 werror(E_LITERAL_GENERIC);
1997 werror(E_NONPTR2_GENPTR);
2000 } else if (implicit) {
2001 werror(W_INTEGRAL2PTR_NOCAST);
2006 // shouldn't do that with float, array or structure unless to void
2007 if (!IS_VOID(getSpec(type)) &&
2008 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2009 werror(E_INCOMPAT_TYPES);
2013 } else { // from a pointer to a pointer
2014 if (IS_GENPTR(type) && IS_VOID(type->next))
2015 { // cast to void* is always allowed
2017 else if (IS_GENPTR(optype) && IS_VOID(optype->next))
2018 { // cast from void* is always allowed
2020 else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
2021 // if not a pointer to a function
2022 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2023 if (implicit) { // if not to generic, they have to match
2024 if (!IS_GENPTR(type) &&
2025 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
2026 ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
2030 werror(E_INCOMPAT_PTYPES);
2037 } else { // to a non pointer
2038 if (IS_PTR(optype)) { // from a pointer
2039 if (implicit) { // sneaky
2040 if (IS_INTEGRAL(type)) {
2041 werror(W_PTR2INTEGRAL_NOCAST);
2043 } else { // shouldn't do that with float, array or structure
2044 werror(E_INCOMPAT_TYPES);
2051 printFromToType (optype, type);
2054 /* if they are the same size create an assignment */
2056 /* This seems very dangerous to me, since there are several */
2057 /* optimizations (for example, gcse) that don't notice the */
2058 /* cast hidden in this assignement and may simplify an */
2059 /* iCode to use the original (uncasted) operand. */
2060 /* Unfortunately, other things break when this cast is */
2061 /* made explicit. Need to fix this someday. */
2062 /* -- EEP, 2004/01/21 */
2063 if (getSize (type) == getSize (optype) &&
2064 !IS_BITFIELD (type) &&
2066 !IS_FLOAT (optype) &&
2068 !IS_FIXED (optype) &&
2069 ((IS_SPEC (type) && IS_SPEC (optype)) ||
2070 (!IS_SPEC (type) && !IS_SPEC (optype))))
2072 ic = newiCode ('=', NULL, op);
2073 IC_RESULT (ic) = newiTempOperand (type, 0);
2074 if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
2075 SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
2076 IC_RESULT (ic)->isaddr = 0;
2080 ic = newiCode (CAST, operandFromLink (type),
2081 geniCodeRValue (op, FALSE));
2083 IC_RESULT (ic) = newiTempOperand (type, 0);
2086 /* preserve the storage class & output class */
2087 /* of the original variable */
2088 restype = getSpec (operandType (IC_RESULT (ic)));
2089 if (!IS_LITERAL(opetype) &&
2092 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2093 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2096 return IC_RESULT (ic);
2099 /*-----------------------------------------------------------------*/
2100 /* geniCodeLabel - will create a Label */
2101 /*-----------------------------------------------------------------*/
2103 geniCodeLabel (symbol * label)
2107 ic = newiCodeLabelGoto (LABEL, label);
2111 /*-----------------------------------------------------------------*/
2112 /* geniCodeGoto - will create a Goto */
2113 /*-----------------------------------------------------------------*/
2115 geniCodeGoto (symbol * label)
2119 ic = newiCodeLabelGoto (GOTO, label);
2123 /*-----------------------------------------------------------------*/
2124 /* geniCodeMultiply - gen intermediate code for multiplication */
2125 /*-----------------------------------------------------------------*/
2127 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2134 /* if they are both literal then we know the result */
2135 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2136 return operandFromValue (valMult (left->operand.valOperand,
2137 right->operand.valOperand));
2139 if (IS_LITERAL(retype)) {
2140 p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2143 resType = usualBinaryConversions (&left, &right, resultType, '*');
2145 rtype = operandType (right);
2146 retype = getSpec (rtype);
2147 ltype = operandType (left);
2148 letype = getSpec (ltype);
2151 /* if the right is a literal & power of 2 */
2152 /* then make it a left shift */
2153 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2154 efficient in most cases than 2 bytes result = 2 bytes << literal
2155 if port has 1 byte muldiv */
2156 if (p2 && !IS_FLOAT (letype) && !IS_FIXED (letype)
2157 && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2158 && (port->support.muldiv == 1))
2159 && strcmp (port->target, "pic16") != 0 /* don't shift for pic */
2160 && strcmp (port->target, "pic14") != 0)
2162 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2164 /* LEFT_OP need same size for left and result, */
2165 left = geniCodeCast (resType, left, TRUE);
2166 ltype = operandType (left);
2168 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2172 ic = newiCode ('*', left, right); /* normal multiplication */
2173 /* if the size left or right > 1 then support routine */
2174 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2178 IC_RESULT (ic) = newiTempOperand (resType, 1);
2181 return IC_RESULT (ic);
2184 /*-----------------------------------------------------------------*/
2185 /* geniCodeDivision - gen intermediate code for division */
2186 /*-----------------------------------------------------------------*/
2188 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2193 sym_link *rtype = operandType (right);
2194 sym_link *retype = getSpec (rtype);
2195 sym_link *ltype = operandType (left);
2196 sym_link *letype = getSpec (ltype);
2198 resType = usualBinaryConversions (&left, &right, resultType, '/');
2200 /* if the right is a literal & power of 2
2201 and left is unsigned then make it a
2203 if (IS_LITERAL (retype) &&
2204 !IS_FLOAT (letype) &&
2205 !IS_FIXED (letype) &&
2206 IS_UNSIGNED(letype) &&
2207 (p2 = powof2 ((TYPE_UDWORD)
2208 floatFromVal (right->operand.valOperand)))) {
2209 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2213 ic = newiCode ('/', left, right); /* normal division */
2214 /* if the size left or right > 1 then support routine */
2215 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2218 IC_RESULT (ic) = newiTempOperand (resType, 0);
2221 return IC_RESULT (ic);
2223 /*-----------------------------------------------------------------*/
2224 /* geniCodeModulus - gen intermediate code for modulus */
2225 /*-----------------------------------------------------------------*/
2227 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2233 /* if they are both literal then we know the result */
2234 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2235 return operandFromValue (valMod (left->operand.valOperand,
2236 right->operand.valOperand));
2238 resType = usualBinaryConversions (&left, &right, resultType, '%');
2240 /* now they are the same size */
2241 ic = newiCode ('%', left, right);
2243 /* if the size left or right > 1 then support routine */
2244 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2246 IC_RESULT (ic) = newiTempOperand (resType, 0);
2249 return IC_RESULT (ic);
2252 /*-----------------------------------------------------------------*/
2253 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2254 /*-----------------------------------------------------------------*/
2256 geniCodePtrPtrSubtract (operand * left, operand * right)
2262 /* if they are both literals then */
2263 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2265 result = operandFromValue (valMinus (left->operand.valOperand,
2266 right->operand.valOperand));
2270 ic = newiCode ('-', left, right);
2272 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2276 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2280 // should we really do this? is this ANSI?
2281 return geniCodeDivision (result,
2282 operandFromLit (getSize (ltype->next)),
2286 /*-----------------------------------------------------------------*/
2287 /* geniCodeSubtract - generates code for subtraction */
2288 /*-----------------------------------------------------------------*/
2290 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2297 /* if they both pointers then */
2298 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2299 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2300 return geniCodePtrPtrSubtract (left, right);
2302 /* if they are both literal then we know the result */
2303 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2304 && left->isLiteral && right->isLiteral)
2305 return operandFromValue (valMinus (left->operand.valOperand,
2306 right->operand.valOperand));
2308 /* if left is an array or pointer */
2309 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2311 isarray = left->isaddr;
2312 right = geniCodeMultiply (right,
2313 operandFromLit (getSize (ltype->next)),
2314 (getArraySizePtr(left) >= INTSIZE) ?
2317 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2320 { /* make them the same size */
2321 resType = usualBinaryConversions (&left, &right, resultType, '-');
2324 ic = newiCode ('-', left, right);
2326 IC_RESULT (ic) = newiTempOperand (resType, 1);
2327 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2329 /* if left or right is a float */
2330 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2331 || IS_FIXED (ltype) || IS_FIXED (rtype))
2335 return IC_RESULT (ic);
2338 /*-----------------------------------------------------------------*/
2339 /* geniCodeAdd - generates iCode for addition */
2340 /*-----------------------------------------------------------------*/
2342 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2351 /* if the right side is LITERAL zero */
2352 /* return the left side */
2353 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2356 /* if left is literal zero return right */
2357 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2360 /* if left is a pointer then size */
2361 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2363 isarray = left->isaddr;
2364 // there is no need to multiply with 1
2365 if (getSize (ltype->next) != 1)
2367 size = operandFromLit (getSize (ltype->next));
2368 SPEC_USIGN (getSpec (operandType (size))) = 1;
2369 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2370 right = geniCodeMultiply (right,
2372 (getArraySizePtr(left) >= INTSIZE) ?
2375 /* Even if right is a 'unsigned char',
2376 the result will be a 'signed int' due to the promotion rules.
2377 It doesn't make sense when accessing arrays, so let's fix it here: */
2379 SPEC_USIGN (getSpec (operandType (right))) = 1;
2381 resType = copyLinkChain (ltype);
2384 { // make them the same size
2385 resType = usualBinaryConversions (&left, &right, resultType, '+');
2388 /* if they are both literals then we know */
2389 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2390 && left->isLiteral && right->isLiteral)
2391 return operandFromValue (valPlus (valFromType (ltype),
2392 valFromType (rtype)));
2394 ic = newiCode ('+', left, right);
2396 IC_RESULT (ic) = newiTempOperand (resType, 1);
2397 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2399 /* if left or right is a float then support
2401 if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2402 || IS_FIXED (ltype) || IS_FIXED (rtype))
2407 return IC_RESULT (ic);
2411 /*-----------------------------------------------------------------*/
2412 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2413 /*-----------------------------------------------------------------*/
2415 aggrToPtr (sym_link * type, bool force)
2420 if (IS_PTR (type) && !force)
2423 etype = getSpec (type);
2424 ptype = newLink (DECLARATOR);
2428 /* set the pointer depending on the storage class */
2429 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2433 /*------------------------------------------------------------------*/
2434 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2435 /*------------------------------------------------------------------*/
2437 aggrToPtrDclType (sym_link * type, bool force)
2439 if (IS_PTR (type) && !force)
2440 return DCL_TYPE (type);
2442 /* return the pointer depending on the storage class */
2443 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2446 /*-----------------------------------------------------------------*/
2447 /* geniCodeArray2Ptr - array to pointer */
2448 /*-----------------------------------------------------------------*/
2450 geniCodeArray2Ptr (operand * op)
2452 sym_link *optype = operandType (op);
2453 sym_link *opetype = getSpec (optype);
2455 /* set the pointer depending on the storage class */
2456 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2463 /*-----------------------------------------------------------------*/
2464 /* geniCodeArray - array access */
2465 /*-----------------------------------------------------------------*/
2467 geniCodeArray (operand * left, operand * right, int lvl)
2471 sym_link *ltype = operandType (left);
2476 if (IS_PTR (ltype->next) && left->isaddr)
2478 left = geniCodeRValue (left, FALSE);
2481 return geniCodeDerefPtr (geniCodeAdd (left,
2483 (getArraySizePtr(left) >= INTSIZE) ?
2489 size = operandFromLit (getSize (ltype->next));
2490 SPEC_USIGN (getSpec (operandType (size))) = 1;
2491 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2492 right = geniCodeMultiply (right,
2494 (getArraySizePtr(left) >= INTSIZE) ?
2497 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2498 It doesn't make sense when accessing arrays, so let's fix it here: */
2500 SPEC_USIGN (getSpec (operandType (right))) = 1;
2501 /* we can check for limits here */
2502 /* already done in SDCCast.c
2503 if (isOperandLiteral (right) &&
2506 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2508 werror (W_IDX_OUT_OF_BOUNDS,
2509 (int) operandLitValue (right) / getSize (ltype->next),
2514 ic = newiCode ('+', left, right);
2516 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2517 !IS_AGGREGATE (ltype->next) &&
2518 !IS_PTR (ltype->next))
2519 ? ltype : ltype->next), 0);
2521 if (!IS_AGGREGATE (ltype->next))
2523 IC_RESULT (ic)->isaddr = 1;
2524 IC_RESULT (ic)->aggr2ptr = 1;
2528 return IC_RESULT (ic);
2531 /*-----------------------------------------------------------------*/
2532 /* geniCodeStruct - generates intermediate code for structures */
2533 /*-----------------------------------------------------------------*/
2535 geniCodeStruct (operand * left, operand * right, bool islval)
2538 sym_link *type = operandType (left);
2539 sym_link *etype = getSpec (type);
2541 symbol *element = getStructElement (SPEC_STRUCT (etype),
2542 right->operand.symOperand);
2544 wassert(IS_SYMOP(right));
2546 /* add the offset */
2547 ic = newiCode ('+', left, operandFromLit (element->offset));
2549 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2551 /* preserve the storage & output class of the struct */
2552 /* as well as the volatile attribute */
2553 retype = getSpec (operandType (IC_RESULT (ic)));
2554 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2555 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2556 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2557 SPEC_CONST (retype) |= SPEC_CONST (etype);
2559 if (IS_PTR (element->type))
2560 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2562 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2565 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2568 /*-----------------------------------------------------------------*/
2569 /* geniCodePostInc - generate int code for Post increment */
2570 /*-----------------------------------------------------------------*/
2572 geniCodePostInc (operand * op)
2576 sym_link *optype = operandType (op);
2578 operand *rv = (IS_ITEMP (op) ?
2579 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2581 sym_link *rvtype = operandType (rv);
2584 /* if this is not an address we have trouble */
2587 werror (E_LVALUE_REQUIRED, "++");
2591 rOp = newiTempOperand (rvtype, 0);
2592 OP_SYMBOL(rOp)->noSpilLoc = 1;
2595 OP_SYMBOL(rv)->noSpilLoc = 1;
2597 geniCodeAssign (rOp, rv, 0, 0);
2599 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2601 werror(W_SIZEOF_VOID);
2602 if (IS_FLOAT (rvtype))
2603 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2605 if (IS_FIXED16X16 (rvtype))
2606 ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2608 ic = newiCode ('+', rv, operandFromLit (size));
2610 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2613 geniCodeAssign (op, result, 0, 0);
2619 /*-----------------------------------------------------------------*/
2620 /* geniCodePreInc - generate code for preIncrement */
2621 /*-----------------------------------------------------------------*/
2623 geniCodePreInc (operand * op, bool lvalue)
2626 sym_link *optype = operandType (op);
2627 operand *rop = (IS_ITEMP (op) ?
2628 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2630 sym_link *roptype = operandType (rop);
2636 werror (E_LVALUE_REQUIRED, "++");
2640 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2642 werror(W_SIZEOF_VOID);
2643 if (IS_FLOAT (roptype))
2644 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2646 if (IS_FIXED16X16 (roptype))
2647 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2649 ic = newiCode ('+', rop, operandFromLit (size));
2650 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2653 (void) geniCodeAssign (op, result, 0, 0);
2654 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2660 /*-----------------------------------------------------------------*/
2661 /* geniCodePostDec - generates code for Post decrement */
2662 /*-----------------------------------------------------------------*/
2664 geniCodePostDec (operand * op)
2668 sym_link *optype = operandType (op);
2670 operand *rv = (IS_ITEMP (op) ?
2671 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2673 sym_link *rvtype = operandType (rv);
2676 /* if this is not an address we have trouble */
2679 werror (E_LVALUE_REQUIRED, "--");
2683 rOp = newiTempOperand (rvtype, 0);
2684 OP_SYMBOL(rOp)->noSpilLoc = 1;
2687 OP_SYMBOL(rv)->noSpilLoc = 1;
2689 geniCodeAssign (rOp, rv, 0, 0);
2691 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2693 werror(W_SIZEOF_VOID);
2694 if (IS_FLOAT (rvtype))
2695 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2697 if (IS_FIXED16X16 (rvtype))
2698 ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2700 ic = newiCode ('-', rv, operandFromLit (size));
2702 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2705 geniCodeAssign (op, result, 0, 0);
2711 /*-----------------------------------------------------------------*/
2712 /* geniCodePreDec - generate code for pre decrement */
2713 /*-----------------------------------------------------------------*/
2715 geniCodePreDec (operand * op, bool lvalue)
2718 sym_link *optype = operandType (op);
2719 operand *rop = (IS_ITEMP (op) ?
2720 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2722 sym_link *roptype = operandType (rop);
2728 werror (E_LVALUE_REQUIRED, "--");
2732 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2734 werror(W_SIZEOF_VOID);
2735 if (IS_FLOAT (roptype))
2736 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2738 if (IS_FIXED16X16 (roptype))
2739 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2741 ic = newiCode ('-', rop, operandFromLit (size));
2742 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2745 (void) geniCodeAssign (op, result, 0, 0);
2746 if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2753 /*-----------------------------------------------------------------*/
2754 /* geniCodeBitwise - gen int code for bitWise operators */
2755 /*-----------------------------------------------------------------*/
2757 geniCodeBitwise (operand * left, operand * right,
2758 int oper, sym_link * resType)
2762 left = geniCodeCast (resType, left, TRUE);
2763 right = geniCodeCast (resType, right, TRUE);
2765 ic = newiCode (oper, left, right);
2766 IC_RESULT (ic) = newiTempOperand (resType, 0);
2769 return IC_RESULT (ic);
2772 /*-----------------------------------------------------------------*/
2773 /* geniCodeAddressOf - gens icode for '&' address of operator */
2774 /*-----------------------------------------------------------------*/
2776 geniCodeAddressOf (operand * op)
2780 sym_link *optype = operandType (op);
2781 sym_link *opetype = getSpec (optype);
2783 if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2785 op = operandFromOperand (op);
2790 /* lvalue check already done in decorateType */
2791 /* this must be a lvalue */
2792 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2793 /* werror (E_LVALUE_REQUIRED,"&"); */
2797 p = newLink (DECLARATOR);
2799 /* set the pointer depending on the storage class */
2800 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2802 p->next = copyLinkChain (optype);
2804 /* if already a temp */
2807 setOperandType (op, p);
2812 /* other wise make this of the type coming in */
2813 ic = newiCode (ADDRESS_OF, op, NULL);
2814 IC_RESULT (ic) = newiTempOperand (p, 1);
2815 IC_RESULT (ic)->isaddr = 0;
2817 return IC_RESULT (ic);
2819 /*-----------------------------------------------------------------*/
2820 /* setOClass - sets the output class depending on the pointer type */
2821 /*-----------------------------------------------------------------*/
2823 setOClass (sym_link * ptr, sym_link * spec)
2825 switch (DCL_TYPE (ptr))
2828 SPEC_OCLS (spec) = data;
2832 SPEC_OCLS (spec) = generic;
2836 SPEC_OCLS (spec) = xdata;
2840 SPEC_OCLS (spec) = code;
2844 SPEC_OCLS (spec) = idata;
2848 SPEC_OCLS (spec) = xstack;
2852 SPEC_OCLS (spec) = eeprom;
2861 /*-----------------------------------------------------------------*/
2862 /* geniCodeDerefPtr - dereference pointer with '*' */
2863 /*-----------------------------------------------------------------*/
2865 geniCodeDerefPtr (operand * op,int lvl)
2867 sym_link *rtype, *retype;
2868 sym_link *optype = operandType (op);
2870 // if this is an array then array access
2871 if (IS_ARRAY (optype)) {
2872 // don't worry, this will be optimized out later
2873 return geniCodeArray (op, operandFromLit (0), lvl);
2876 // just in case someone screws up
2877 wassert (IS_PTR (optype));
2879 if (IS_TRUE_SYMOP (op))
2882 op = geniCodeRValue (op, TRUE);
2885 /* now get rid of the pointer part */
2886 if (isLvaluereq(lvl) && IS_ITEMP (op))
2888 retype = getSpec (rtype = copyLinkChain (optype));
2892 retype = getSpec (rtype = copyLinkChain (optype->next));
2893 /* outputclass needs 2b updated */
2894 setOClass (optype, retype);
2897 op->isGptr = IS_GENPTR (optype);
2899 op->isaddr = (IS_PTR (rtype) ||
2900 IS_STRUCT (rtype) ||
2906 if (!isLvaluereq(lvl))
2907 op = geniCodeRValue (op, TRUE);
2909 setOperandType (op, rtype);
2914 /*-----------------------------------------------------------------*/
2915 /* geniCodeUnaryMinus - does a unary minus of the operand */
2916 /*-----------------------------------------------------------------*/
2918 geniCodeUnaryMinus (operand * op)
2921 sym_link *optype = operandType (op);
2923 if (IS_LITERAL (optype))
2924 return operandFromLit (-floatFromVal (op->operand.valOperand));
2926 ic = newiCode (UNARYMINUS, op, NULL);
2927 IC_RESULT (ic) = newiTempOperand (optype, 0);
2929 return IC_RESULT (ic);
2932 /*-----------------------------------------------------------------*/
2933 /* geniCodeLeftShift - gen i code for left shift */
2934 /*-----------------------------------------------------------------*/
2936 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2941 ic = newiCode (LEFT_OP, left, right);
2943 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2944 IC_RESULT (ic) = newiTempOperand (resType, 0);
2946 return IC_RESULT (ic);
2949 /*-----------------------------------------------------------------*/
2950 /* geniCodeRightShift - gen i code for right shift */
2951 /*-----------------------------------------------------------------*/
2953 geniCodeRightShift (operand * left, operand * right)
2957 ic = newiCode (RIGHT_OP, left, right);
2958 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2960 return IC_RESULT (ic);
2963 /*-----------------------------------------------------------------*/
2964 /* geniCodeLogic- logic code */
2965 /*-----------------------------------------------------------------*/
2967 geniCodeLogic (operand * left, operand * right, int op)
2971 sym_link *rtype = operandType (right);
2972 sym_link *ltype = operandType (left);
2974 /* left is integral type and right is literal then
2975 check if the literal value is within bounds */
2976 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2978 checkConstantRange(ltype,
2979 OP_VALUE(right), "compare operation", 1);
2982 /* if one operand is a pointer and the other is a literal generic void pointer,
2983 change the type of the literal generic void pointer to match the other pointer */
2984 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2985 && IS_PTR (rtype) && !IS_GENPTR(rtype))
2987 /* find left's definition */
2988 ic = (iCode *) setFirstItem (iCodeChain);
2991 if (((ic->op == CAST) || (ic->op == '='))
2992 && isOperandEqual(left, IC_RESULT (ic)))
2995 ic = setNextItem (iCodeChain);
2997 /* if casting literal to generic pointer, then cast to rtype instead */
2998 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
3000 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
3001 ltype = operandType(left);
3004 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
3005 && IS_PTR (ltype) && !IS_GENPTR(ltype))
3007 /* find right's definition */
3008 ic = (iCode *) setFirstItem (iCodeChain);
3011 if (((ic->op == CAST) || (ic->op == '='))
3012 && isOperandEqual(right, IC_RESULT (ic)))
3015 ic = setNextItem (iCodeChain);
3017 /* if casting literal to generic pointer, then cast to rtype instead */
3018 if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
3020 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
3021 rtype = operandType(right);
3025 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
3027 ic = newiCode (op, left, right);
3028 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
3030 /* if comparing float
3031 and not a '==' || '!=' || '&&' || '||' (these
3033 if (IS_FLOAT(ctype) &&
3040 /* if comparing a fixed type use support functions */
3041 if (IS_FIXED(ctype))
3045 return IC_RESULT (ic);
3048 /*-----------------------------------------------------------------*/
3049 /* geniCodeLogicAndOr - && || operations */
3050 /*-----------------------------------------------------------------*/
3052 geniCodeLogicAndOr (ast *tree, int lvl)
3056 symbol *falseLabel = newiTempLabel (NULL);
3057 symbol *trueLabel = newiTempLabel (NULL);
3058 symbol *exitLabel = newiTempLabel (NULL);
3059 operand *op, *result, *condition;
3061 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3062 They can be reenabled by executing the following block. If you find
3063 a decent optimization you could start right here:
3068 operand *leftOp, *rightOp;
3070 leftOp = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3071 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3073 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3077 /* generate two IFX for the '&&' or '||' op */
3079 /* evaluate left operand */
3080 condition = ast2iCode (tree->left, lvl + 1);
3081 op = geniCodeRValue (condition, FALSE);
3083 /* test left operand */
3084 if (tree->opval.op == AND_OP)
3085 ic = newiCodeCondition (op, NULL, falseLabel);
3087 ic = newiCodeCondition (op, trueLabel, NULL);
3090 /* evaluate right operand */
3091 condition = ast2iCode (tree->right, lvl + 1);
3092 op = geniCodeRValue (condition, FALSE);
3094 /* test right operand */
3095 ic = newiCodeCondition (op, trueLabel, NULL);
3098 /* store 0 or 1 in result */
3099 type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
3100 result = newiTempOperand (type, 1);
3102 geniCodeLabel (falseLabel);
3103 geniCodeAssign (result, operandFromLit (0), 0, 0);
3104 /* generate an unconditional goto */
3105 geniCodeGoto (exitLabel);
3107 geniCodeLabel (trueLabel);
3108 geniCodeAssign (result, operandFromLit (1), 0, 0);
3110 geniCodeLabel (exitLabel);
3115 /*-----------------------------------------------------------------*/
3116 /* geniCodeUnary - for a generic unary operation */
3117 /*-----------------------------------------------------------------*/
3119 geniCodeUnary (operand * op, int oper)
3121 iCode *ic = newiCode (oper, op, NULL);
3123 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3125 return IC_RESULT (ic);
3128 /*-----------------------------------------------------------------*/
3129 /* geniCodeBinary - for a generic binary operation */
3130 /*-----------------------------------------------------------------*/
3132 geniCodeBinary (operand * left, operand * right, int oper)
3134 iCode *ic = newiCode (oper, left, right);
3136 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3138 return IC_RESULT (ic);
3141 /*-----------------------------------------------------------------*/
3142 /* geniCodeConditional - geniCode for '?' ':' operation */
3143 /*-----------------------------------------------------------------*/
3145 geniCodeConditional (ast * tree,int lvl)
3148 symbol *falseLabel = newiTempLabel (NULL);
3149 symbol *exitLabel = newiTempLabel (NULL);
3150 operand *cond = ast2iCode (tree->left,lvl+1);
3151 operand *true, *false, *result;
3153 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3157 true = ast2iCode (tree->right->left,lvl+1);
3159 /* move the value to a new Operand */
3160 result = newiTempOperand (tree->right->ftype, 0);
3161 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3163 /* generate an unconditional goto */
3164 geniCodeGoto (exitLabel);
3166 /* now for the right side */
3167 geniCodeLabel (falseLabel);
3169 false = ast2iCode (tree->right->right,lvl+1);
3170 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3172 /* create the exit label */
3173 geniCodeLabel (exitLabel);
3178 /*-----------------------------------------------------------------*/
3179 /* geniCodeAssign - generate code for assignment */
3180 /*-----------------------------------------------------------------*/
3182 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3185 sym_link *ltype = operandType (left);
3186 sym_link *rtype = operandType (right);
3188 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3190 werror (E_LVALUE_REQUIRED, "assignment");
3194 /* left is integral type and right is literal then
3195 check if the literal value is within bounds */
3196 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3198 checkConstantRange(ltype,
3199 OP_VALUE(right), "= operation", 0);
3202 /* if the left & right type don't exactly match */
3203 /* if pointer set then make sure the check is
3204 done with the type & not the pointer */
3205 /* then cast rights type to left */
3207 /* first check the type for pointer assignement */
3208 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3209 compareType (ltype, rtype) <= 0)
3211 if (compareType (ltype->next, rtype) < 0)
3212 right = geniCodeCast (ltype->next, right, TRUE);
3214 else if (compareType (ltype, rtype) < 0)
3215 right = geniCodeCast (ltype, right, TRUE);
3217 /* If left is a true symbol & ! volatile
3218 create an assignment to temporary for
3219 the right & then assign this temporary
3220 to the symbol. This is SSA (static single
3221 assignment). Isn't it simple and folks have
3222 published mountains of paper on it */
3223 if (IS_TRUE_SYMOP (left) &&
3224 !isOperandVolatile (left, FALSE) &&
3225 isOperandGlobal (left))
3229 if (IS_TRUE_SYMOP (right))
3230 sym = OP_SYMBOL (right);
3231 ic = newiCode ('=', NULL, right);
3232 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3233 SPIL_LOC (right) = sym;
3237 ic = newiCode ('=', NULL, right);
3238 IC_RESULT (ic) = left;
3241 /* if left isgptr flag is set then support
3242 routine will be required */
3246 ic->nosupdate = nosupdate;
3250 /*-----------------------------------------------------------------*/
3251 /* geniCodeDummyRead - generate code for dummy read */
3252 /*-----------------------------------------------------------------*/
3254 geniCodeDummyRead (operand * op)
3257 sym_link *type = operandType (op);
3259 if (!IS_VOLATILE(type))
3262 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3268 /*-----------------------------------------------------------------*/
3269 /* geniCodeSEParms - generate code for side effecting fcalls */
3270 /*-----------------------------------------------------------------*/
3272 geniCodeSEParms (ast * parms,int lvl)
3277 if (parms->type == EX_OP && parms->opval.op == PARAM)
3279 geniCodeSEParms (parms->left,lvl);
3280 geniCodeSEParms (parms->right,lvl);
3284 /* hack don't like this but too lazy to think of
3286 if (IS_ADDRESS_OF_OP (parms))
3287 parms->left->lvalue = 1;
3289 if (IS_CAST_OP (parms) &&
3290 IS_PTR (parms->ftype) &&
3291 IS_ADDRESS_OF_OP (parms->right))
3292 parms->right->left->lvalue = 1;
3294 parms->opval.oprnd =
3295 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3297 parms->type = EX_OPERAND;
3298 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3299 SPEC_ARGREG(parms->ftype);
3302 /*-----------------------------------------------------------------*/
3303 /* geniCodeParms - generates parameters */
3304 /*-----------------------------------------------------------------*/
3306 geniCodeParms (ast * parms, value *argVals, int *stack,
3307 sym_link * ftype, int lvl)
3315 if (argVals==NULL) {
3317 argVals = FUNC_ARGS (ftype);
3320 /* if this is a param node then do the left & right */
3321 if (parms->type == EX_OP && parms->opval.op == PARAM)
3323 argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3324 argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3328 /* get the parameter value */
3329 if (parms->type == EX_OPERAND)
3330 pval = parms->opval.oprnd;
3333 /* maybe this else should go away ?? */
3334 /* hack don't like this but too lazy to think of
3336 if (IS_ADDRESS_OF_OP (parms))
3337 parms->left->lvalue = 1;
3339 if (IS_CAST_OP (parms) &&
3340 IS_PTR (parms->ftype) &&
3341 IS_ADDRESS_OF_OP (parms->right))
3342 parms->right->left->lvalue = 1;
3344 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3347 /* if register parm then make it a send */
3348 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3349 IFFUNC_ISBUILTIN(ftype))
3351 ic = newiCode (SEND, pval, NULL);
3352 ic->argreg = SPEC_ARGREG(parms->etype);
3353 ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3358 /* now decide whether to push or assign */
3359 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3363 operand *top = operandFromSymbol (argVals->sym);
3364 /* clear useDef and other bitVectors */
3365 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3366 geniCodeAssign (top, pval, 1, 0);
3370 sym_link *p = operandType (pval);
3372 ic = newiCode (IPUSH, pval, NULL);
3374 /* update the stack adjustment */
3375 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3380 argVals=argVals->next;
3384 /*-----------------------------------------------------------------*/
3385 /* geniCodeCall - generates temp code for calling */
3386 /*-----------------------------------------------------------------*/
3388 geniCodeCall (operand * left, ast * parms,int lvl)
3392 sym_link *type, *etype;
3396 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3397 !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3398 werror (E_FUNCTION_EXPECTED);
3399 return operandFromValue(valueFromLit(0));
3402 /* take care of parameters with side-effecting
3403 function calls in them, this is required to take care
3404 of overlaying function parameters */
3405 geniCodeSEParms (parms,lvl);
3407 ftype = operandType (left);
3408 if (IS_FUNCPTR (ftype))
3409 ftype = ftype->next;
3411 /* first the parameters */
3412 geniCodeParms (parms, NULL, &stack, ftype, lvl);
3414 /* now call : if symbol then pcall */
3415 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3416 ic = newiCode (PCALL, left, NULL);
3418 ic = newiCode (CALL, left, NULL);
3421 type = copyLinkChain (ftype->next);
3422 etype = getSpec (type);
3423 SPEC_EXTR (etype) = 0;
3424 IC_RESULT (ic) = result = newiTempOperand (type, 1);
3428 /* stack adjustment after call */
3429 ic->parmBytes = stack;
3434 /*-----------------------------------------------------------------*/
3435 /* geniCodeReceive - generate intermediate code for "receive" */
3436 /*-----------------------------------------------------------------*/
3438 geniCodeReceive (value * args, operand * func)
3440 unsigned char paramByteCounter = 0;
3442 /* for all arguments that are passed in registers */
3445 if (IS_REGPARM (args->etype))
3447 operand *opr = operandFromValue (args);
3449 symbol *sym = OP_SYMBOL (opr);
3452 /* we will use it after all optimizations
3453 and before liveRange calculation */
3454 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3457 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3458 options.stackAuto == 0 &&
3459 (!(options.model == MODEL_FLAT24)) )
3464 opl = newiTempOperand (args->type, 0);
3466 sym->reqv->key = sym->key;
3467 OP_SYMBOL (sym->reqv)->key = sym->key;
3468 OP_SYMBOL (sym->reqv)->isreqv = 1;
3469 OP_SYMBOL (sym->reqv)->islocal = 0;
3470 SPIL_LOC (sym->reqv) = sym;
3474 ic = newiCode (RECEIVE, func, NULL);
3475 ic->argreg = SPEC_ARGREG(args->etype);
3476 if (ic->argreg == 1) {
3477 currFunc->recvSize = getSize (sym->type);
3479 IC_RESULT (ic) = opr;
3481 /* misuse of parmBytes (normally used for functions)
3482 * to save estimated stack position of this argument.
3483 * Normally this should be zero for RECEIVE iCodes.
3484 * No idea if this causes side effects on other ports. - dw
3486 ic->parmBytes = paramByteCounter;
3488 /* what stack position do we have? */
3489 paramByteCounter += getSize (sym->type);
3498 /*-----------------------------------------------------------------*/
3499 /* geniCodeFunctionBody - create the function body */
3500 /*-----------------------------------------------------------------*/
3502 geniCodeFunctionBody (ast * tree,int lvl)
3509 /* reset the auto generation */
3515 func = ast2iCode (tree->left,lvl+1);
3516 fetype = getSpec (operandType (func));
3518 savelineno = lineno;
3519 lineno = OP_SYMBOL (func)->lineDef;
3520 /* create an entry label */
3521 geniCodeLabel (entryLabel);
3522 lineno = savelineno;
3524 /* create a proc icode */
3525 ic = newiCode (FUNCTION, func, NULL);
3526 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3531 /* for all parameters that are passed
3532 on registers add a "receive" */
3533 geniCodeReceive (tree->values.args, func);
3535 /* generate code for the body */
3536 ast2iCode (tree->right,lvl+1);
3538 /* create a label for return */
3539 geniCodeLabel (returnLabel);
3541 /* now generate the end proc */
3542 ic = newiCode (ENDFUNCTION, func, NULL);
3548 /*-----------------------------------------------------------------*/
3549 /* geniCodeReturn - gen icode for 'return' statement */
3550 /*-----------------------------------------------------------------*/
3552 geniCodeReturn (operand * op)
3556 /* if the operand is present force an rvalue */
3558 op = geniCodeRValue (op, FALSE);
3560 ic = newiCode (RETURN, op, NULL);
3564 /*-----------------------------------------------------------------*/
3565 /* geniCodeIfx - generates code for extended if statement */
3566 /*-----------------------------------------------------------------*/
3568 geniCodeIfx (ast * tree,int lvl)
3571 operand *condition = ast2iCode (tree->left,lvl+1);
3574 /* if condition is null then exit */
3578 condition = geniCodeRValue (condition, FALSE);
3580 cetype = getSpec (operandType (condition));
3581 /* if the condition is a literal */
3582 if (IS_LITERAL (cetype))
3584 if (floatFromVal (condition->operand.valOperand))
3586 if (tree->trueLabel)
3587 geniCodeGoto (tree->trueLabel);
3593 if (tree->falseLabel)
3594 geniCodeGoto (tree->falseLabel);
3601 if (tree->trueLabel)
3603 ic = newiCodeCondition (condition,
3608 if (tree->falseLabel)
3609 geniCodeGoto (tree->falseLabel);
3613 ic = newiCodeCondition (condition,
3620 ast2iCode (tree->right,lvl+1);
3623 /*-----------------------------------------------------------------*/
3624 /* geniCodeJumpTable - tries to create a jump table for switch */
3625 /*-----------------------------------------------------------------*/
3627 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3629 int min, max, cnt = 1;
3636 int needRangeCheck = !optimize.noJTabBoundary
3637 || tree->values.switchVals.swDefault;
3638 sym_link *cetype = getSpec (operandType (cond));
3639 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3640 int sizeofMatchJump, sizeofJumpTable;
3643 if (!tree || !caseVals)
3646 /* the criteria for creating a jump table is */
3647 /* all integer numbers between the maximum & minimum must */
3648 /* be present , the maximum value should not exceed 255 */
3649 /* If not all integer numbers are present the algorithm */
3650 /* inserts jumps to the default label for the missing numbers */
3651 /* and decides later whether it is worth it */
3652 min = (int) floatFromVal (vch = caseVals);
3659 max = (int) floatFromVal (vch);
3661 /* Exit if the range is too large to handle with a jump table. */
3662 if (1 + max - min > port->jumptableCost.maxCount)
3665 switch (getSize (operandType (cond)))
3667 case 1: sizeIndex = 0; break;
3668 case 2: sizeIndex = 1; break;
3669 case 4: sizeIndex = 2; break;
3673 /* Compute the size cost of the range check and subtraction. */
3675 sizeofZeroMinCost = 0;
3679 if (!(min==0 && IS_UNSIGNED (cetype)))
3680 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3681 if (!IS_UNSIGNED (cetype))
3682 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3683 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3686 sizeofMinCost += port->jumptableCost.sizeofSubtract;
3688 /* If the size cost of handling a non-zero minimum exceeds the */
3689 /* cost of extending the range down to zero, then it might be */
3690 /* better to extend the range to zero. */
3691 if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3692 >= (min * port->jumptableCost.sizeofElement))
3694 /* Only extend the jump table if it would still be manageable. */
3695 if (1 + max <= port->jumptableCost.maxCount)
3698 if (IS_UNSIGNED (cetype))
3701 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3705 /* Compute the total size cost of a jump table. */
3706 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3707 + port->jumptableCost.sizeofDispatch
3708 + sizeofMinCost + sizeofMaxCost;
3710 /* Compute the total size cost of a match & jump sequence */
3711 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3713 /* If the size cost of the jump table is uneconomical then exit */
3714 if (sizeofMatchJump < sizeofJumpTable)
3717 /* The jump table is preferable. */
3719 /* First, a label for the default or missing cases. */
3720 if (tree->values.switchVals.swDefault)
3722 SNPRINTF (buffer, sizeof(buffer),
3724 tree->values.switchVals.swNum);
3728 SNPRINTF (buffer, sizeof(buffer),
3730 tree->values.switchVals.swNum);
3732 falseLabel = newiTempLabel (buffer);
3734 /* Build the list of labels for the jump table. */
3736 t = (int) floatFromVal (vch);
3737 for (i=min; i<=max; i++)
3741 /* Explicit case: make a new label for it. */
3742 SNPRINTF (buffer, sizeof(buffer),
3744 tree->values.switchVals.swNum,
3746 addSet (&labels, newiTempLabel (buffer));
3749 t = (int) floatFromVal (vch);
3753 /* Implicit case: use the default label. */
3754 addSet (&labels, falseLabel);
3758 /* first we rule out the boundary conditions */
3759 /* if only optimization says so */
3762 sym_link *cetype = getSpec (operandType (cond));
3763 /* no need to check the lower bound if
3764 the condition is unsigned & minimum value is zero */
3765 if (!(min == 0 && IS_UNSIGNED (cetype)))
3767 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3768 ic = newiCodeCondition (boundary, falseLabel, NULL);
3772 /* now for upper bounds */
3773 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3774 ic = newiCodeCondition (boundary, falseLabel, NULL);
3778 /* if the min is not zero then we no make it zero */
3781 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3782 if (!IS_LITERAL(getSpec(operandType(cond))))
3783 setOperandType (cond, UCHARTYPE);
3786 /* now create the jumptable */
3787 ic = newiCode (JUMPTABLE, NULL, NULL);
3788 IC_JTCOND (ic) = cond;
3789 IC_JTLABELS (ic) = labels;
3794 /*-----------------------------------------------------------------*/
3795 /* geniCodeSwitch - changes a switch to a if statement */
3796 /*-----------------------------------------------------------------*/
3798 geniCodeSwitch (ast * tree,int lvl)
3801 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3802 value *caseVals = tree->values.switchVals.swVals;
3803 symbol *trueLabel, *falseLabel;
3805 /* If the condition is a literal, then just jump to the */
3806 /* appropriate case label. */
3807 if (IS_LITERAL(getSpec(operandType(cond))))
3809 int switchVal, caseVal;
3811 switchVal = (int) floatFromVal (cond->operand.valOperand);
3814 caseVal = (int) floatFromVal (caseVals);
3815 if (caseVal == switchVal)
3817 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3818 tree->values.switchVals.swNum, caseVal);
3819 trueLabel = newiTempLabel (buffer);
3820 geniCodeGoto (trueLabel);
3823 caseVals = caseVals->next;
3825 goto defaultOrBreak;
3828 /* If cond is volatile, it might change while we are trying to */
3829 /* find the matching case. To avoid this possibility, make a */
3830 /* non-volatile copy to use instead. */
3831 if (IS_OP_VOLATILE (cond))
3836 newcond = newiTempOperand (operandType (cond), TRUE);
3837 newcond->isvolatile = 0;
3838 ic = newiCode ('=', NULL, cond);
3839 IC_RESULT (ic) = newcond;
3844 /* if we can make this a jump table */
3845 if (geniCodeJumpTable (cond, caseVals, tree))
3846 goto jumpTable; /* no need for the comparison */
3848 /* for the cases defined do */
3852 operand *compare = geniCodeLogic (cond,
3853 operandFromValue (caseVals),
3856 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3857 tree->values.switchVals.swNum,
3858 (int) floatFromVal (caseVals));
3859 trueLabel = newiTempLabel (buffer);
3861 ic = newiCodeCondition (compare, trueLabel, NULL);
3863 caseVals = caseVals->next;
3868 /* if default is present then goto break else break */
3869 if (tree->values.switchVals.swDefault)
3871 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3875 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3878 falseLabel = newiTempLabel (buffer);
3879 geniCodeGoto (falseLabel);
3882 ast2iCode (tree->right,lvl+1);
3885 /*-----------------------------------------------------------------*/
3886 /* geniCodeInline - intermediate code for inline assembler */
3887 /*-----------------------------------------------------------------*/
3889 geniCodeInline (ast * tree)
3893 ic = newiCode (INLINEASM, NULL, NULL);
3894 IC_INLINE (ic) = tree->values.inlineasm;
3898 /*-----------------------------------------------------------------*/
3899 /* geniCodeArrayInit - intermediate code for array initializer */
3900 /*-----------------------------------------------------------------*/
3902 geniCodeArrayInit (ast * tree, operand *array)
3906 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3907 ic = newiCode (ARRAYINIT, array, NULL);
3908 IC_ARRAYILIST (ic) = tree->values.constlist;
3910 operand *left=newOperand(), *right=newOperand();
3911 left->type=right->type=SYMBOL;
3912 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3913 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3914 ic = newiCode (ARRAYINIT, left, right);
3919 /*-----------------------------------------------------------------*/
3920 /* geniCodeCritical - intermediate code for a critical statement */
3921 /*-----------------------------------------------------------------*/
3923 geniCodeCritical (ast *tree, int lvl)
3929 if (!options.stackAuto)
3931 type = newLink(SPECIFIER);
3932 SPEC_VOLATILE(type) = 1;
3933 SPEC_NOUN(type) = V_BIT;
3934 SPEC_SCLS(type) = S_BIT;
3935 SPEC_BLEN(type) = 1;
3936 SPEC_BSTR(type) = 0;
3937 op = newiTempOperand(type, 1);
3940 /* If op is NULL, the original interrupt state will saved on */
3941 /* the stack. Otherwise, it will be saved in op. */
3943 /* Generate a save of the current interrupt state & disable */
3944 ic = newiCode (CRITICAL, NULL, NULL);
3945 IC_RESULT (ic) = op;
3948 /* Generate the critical code sequence */
3949 if (tree->left && tree->left->type == EX_VALUE)
3950 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3952 ast2iCode (tree->left,lvl+1);
3954 /* Generate a restore of the original interrupt state */
3955 ic = newiCode (ENDCRITICAL, NULL, op);
3959 /*-----------------------------------------------------------------*/
3960 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3961 /* particular case. Ie : assigning or dereferencing array or ptr */
3962 /*-----------------------------------------------------------------*/
3963 set * lvaluereqSet = NULL;
3964 typedef struct lvalItem
3971 /*-----------------------------------------------------------------*/
3972 /* addLvaluereq - add a flag for lvalreq for current ast level */
3973 /*-----------------------------------------------------------------*/
3974 void addLvaluereq(int lvl)
3976 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3979 addSetHead(&lvaluereqSet,lpItem);
3982 /*-----------------------------------------------------------------*/
3983 /* delLvaluereq - del a flag for lvalreq for current ast level */
3984 /*-----------------------------------------------------------------*/
3988 lpItem = getSet(&lvaluereqSet);
3989 if(lpItem) Safe_free(lpItem);
3991 /*-----------------------------------------------------------------*/
3992 /* clearLvaluereq - clear lvalreq flag */
3993 /*-----------------------------------------------------------------*/
3994 void clearLvaluereq()
3997 lpItem = peekSet(lvaluereqSet);
3998 if(lpItem) lpItem->req = 0;
4000 /*-----------------------------------------------------------------*/
4001 /* getLvaluereq - get the last lvalreq level */
4002 /*-----------------------------------------------------------------*/
4003 int getLvaluereqLvl()
4006 lpItem = peekSet(lvaluereqSet);
4007 if(lpItem) return lpItem->lvl;
4010 /*-----------------------------------------------------------------*/
4011 /* isLvaluereq - is lvalreq valid for this level ? */
4012 /*-----------------------------------------------------------------*/
4013 int isLvaluereq(int lvl)
4016 lpItem = peekSet(lvaluereqSet);
4017 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
4021 /*-----------------------------------------------------------------*/
4022 /* ast2iCode - creates an icodeList from an ast */
4023 /*-----------------------------------------------------------------*/
4025 ast2iCode (ast * tree,int lvl)
4027 operand *left = NULL;
4028 operand *right = NULL;
4032 /* set the global variables for filename & line number */
4034 filename = tree->filename;
4036 lineno = tree->lineno;
4038 block = tree->block;
4040 scopeLevel = tree->level;
4042 seqPoint = tree->seqPoint;
4044 if (tree->type == EX_VALUE)
4045 return operandFromValue (tree->opval.val);
4047 if (tree->type == EX_LINK)
4048 return operandFromLink (tree->opval.lnk);
4050 /* if we find a nullop */
4051 if (tree->type == EX_OP &&
4052 (tree->opval.op == NULLOP ||
4053 tree->opval.op == BLOCK))
4055 if (tree->left && tree->left->type == EX_VALUE)
4056 geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4058 ast2iCode (tree->left,lvl+1);
4059 if (tree->right && tree->right->type == EX_VALUE)
4060 geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4062 ast2iCode (tree->right,lvl+1);
4066 /* special cases for not evaluating */
4067 if (tree->opval.op != ':' &&
4068 tree->opval.op != '?' &&
4069 tree->opval.op != CALL &&
4070 tree->opval.op != IFX &&
4071 tree->opval.op != AND_OP &&
4072 tree->opval.op != OR_OP &&
4073 tree->opval.op != LABEL &&
4074 tree->opval.op != GOTO &&
4075 tree->opval.op != SWITCH &&
4076 tree->opval.op != FUNCTION &&
4077 tree->opval.op != INLINEASM &&
4078 tree->opval.op != CRITICAL)
4081 if (IS_ASSIGN_OP (tree->opval.op) ||
4082 IS_DEREF_OP (tree) ||
4083 (tree->opval.op == '&' && !tree->right) ||
4084 tree->opval.op == PTR_OP)
4087 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4088 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4091 left = operandFromAst (tree->left,lvl);
4093 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4094 left = geniCodeRValue (left, TRUE);
4098 left = operandFromAst (tree->left,lvl);
4100 if (tree->opval.op == INC_OP ||
4101 tree->opval.op == DEC_OP)
4104 right = operandFromAst (tree->right,lvl);
4109 right = operandFromAst (tree->right,lvl);
4113 /* now depending on the type of operand */
4114 /* this will be a biggy */
4115 switch (tree->opval.op)
4118 case '[': /* array operation */
4120 //sym_link *ltype = operandType (left);
4121 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4122 left = geniCodeRValue (left, FALSE);
4123 right = geniCodeRValue (right, TRUE);
4126 return geniCodeArray (left, right,lvl);
4128 case '.': /* structure dereference */
4129 if (IS_PTR (operandType (left)))
4130 left = geniCodeRValue (left, TRUE);
4132 left = geniCodeRValue (left, FALSE);
4134 return geniCodeStruct (left, right, tree->lvalue);
4136 case PTR_OP: /* structure pointer dereference */
4139 pType = operandType (left);
4140 left = geniCodeRValue (left, TRUE);
4142 setOClass (pType, getSpec (operandType (left)));
4145 return geniCodeStruct (left, right, tree->lvalue);
4147 case INC_OP: /* increment operator */
4149 return geniCodePostInc (left);
4151 return geniCodePreInc (right, tree->lvalue);
4153 case DEC_OP: /* decrement operator */
4155 return geniCodePostDec (left);
4157 return geniCodePreDec (right, tree->lvalue);
4159 case '&': /* bitwise and or address of operator */
4161 { /* this is a bitwise operator */
4162 left = geniCodeRValue (left, FALSE);
4163 right = geniCodeRValue (right, FALSE);
4164 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4167 return geniCodeAddressOf (left);
4169 case '|': /* bitwise or & xor */
4171 return geniCodeBitwise (geniCodeRValue (left, FALSE),
4172 geniCodeRValue (right, FALSE),
4177 return geniCodeDivision (geniCodeRValue (left, FALSE),
4178 geniCodeRValue (right, FALSE),
4179 getResultTypeFromType (tree->ftype));
4182 return geniCodeModulus (geniCodeRValue (left, FALSE),
4183 geniCodeRValue (right, FALSE),
4184 getResultTypeFromType (tree->ftype));
4187 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4188 geniCodeRValue (right, FALSE),
4189 getResultTypeFromType (tree->ftype));
4191 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4195 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4196 geniCodeRValue (right, FALSE),
4197 getResultTypeFromType (tree->ftype));
4199 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4203 return geniCodeAdd (geniCodeRValue (left, FALSE),
4204 geniCodeRValue (right, FALSE),
4205 getResultTypeFromType (tree->ftype),
4208 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4211 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4212 geniCodeRValue (right, FALSE),
4213 getResultTypeFromType (tree->ftype));
4216 return geniCodeRightShift (geniCodeRValue (left, FALSE),
4217 geniCodeRValue (right, FALSE));
4219 #if 0 // this indeed needs a second thought
4223 // let's keep this simple: get the rvalue we need
4224 op=geniCodeRValue (right, FALSE);
4225 // now cast it to whatever we want
4226 op=geniCodeCast (operandType(left), op, FALSE);
4227 // if this is going to be used as an lvalue, make it so
4233 #else // bug #604575, is it a bug ????
4234 return geniCodeCast (operandType (left),
4235 geniCodeRValue (right, FALSE), FALSE);
4240 sym_link *ltype = operandType (left);
4241 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4242 if ((SPEC_NOUN(ltype) == V_CHAR) && IS_UNSIGNED(ltype))
4244 setOperandType (op, INTTYPE);
4251 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4256 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4257 setOperandType (op, UCHARTYPE);
4264 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4265 geniCodeRValue (right, FALSE),
4267 setOperandType (op, (tree->opval.op == GETWORD) ? UINTTYPE : UCHARTYPE);
4272 return geniCodeLogicAndOr (tree, lvl);
4279 /* different compilers (even different gccs) evaluate
4280 the two calls in a different order. to get the same
4281 result on all machines we've to specify a clear sequence.
4282 return geniCodeLogic (geniCodeRValue (left, FALSE),
4283 geniCodeRValue (right, FALSE),
4287 operand *leftOp, *rightOp;
4289 leftOp = geniCodeRValue (left , FALSE);
4290 rightOp = geniCodeRValue (right, FALSE);
4292 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4295 return geniCodeConditional (tree,lvl);
4298 return operandFromLit (getSize (tree->right->ftype));
4302 sym_link *rtype = operandType (right);
4303 sym_link *ltype = operandType (left);
4304 if (IS_PTR (rtype) && IS_ITEMP (right)
4305 && right->isaddr && compareType (rtype->next, ltype) == 1)
4306 right = geniCodeRValue (right, TRUE);
4308 right = geniCodeRValue (right, FALSE);
4310 geniCodeAssign (left, right, 0, 1);
4315 geniCodeAssign (left,
4316 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4318 geniCodeRValue (right, FALSE),
4319 getResultTypeFromType (tree->ftype)),
4324 geniCodeAssign (left,
4325 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4327 geniCodeRValue (right, FALSE),
4328 getResultTypeFromType (tree->ftype)),
4332 geniCodeAssign (left,
4333 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4335 geniCodeRValue (right, FALSE),
4336 getResultTypeFromType (tree->ftype)),
4340 sym_link *rtype = operandType (right);
4341 sym_link *ltype = operandType (left);
4342 if (IS_PTR (rtype) && IS_ITEMP (right)
4343 && right->isaddr && compareType (rtype->next, ltype) == 1)
4344 right = geniCodeRValue (right, TRUE);
4346 right = geniCodeRValue (right, FALSE);
4349 return geniCodeAssign (left,
4350 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4353 getResultTypeFromType (tree->ftype),
4359 sym_link *rtype = operandType (right);
4360 sym_link *ltype = operandType (left);
4361 if (IS_PTR (rtype) && IS_ITEMP (right)
4362 && right->isaddr && compareType (rtype->next, ltype) == 1)
4364 right = geniCodeRValue (right, TRUE);
4368 right = geniCodeRValue (right, FALSE);
4371 geniCodeAssign (left,
4372 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4375 getResultTypeFromType (tree->ftype)),
4380 geniCodeAssign (left,
4381 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4383 geniCodeRValue (right, FALSE),
4384 getResultTypeFromType (tree->ftype)),
4388 geniCodeAssign (left,
4389 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4391 geniCodeRValue (right, FALSE)), 0, 1);
4394 geniCodeAssign (left,
4395 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4397 geniCodeRValue (right, FALSE),
4399 operandType (left)), 0, 1);
4402 geniCodeAssign (left,
4403 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4405 geniCodeRValue (right, FALSE),
4407 operandType (left)), 0, 1);
4410 geniCodeAssign (left,
4411 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4413 geniCodeRValue (right, FALSE),
4415 operandType (left)), 0, 1);
4417 return geniCodeRValue (right, FALSE);
4420 return geniCodeCall (ast2iCode (tree->left,lvl+1),
4423 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4424 return ast2iCode (tree->right,lvl+1);
4427 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4428 return ast2iCode (tree->right,lvl+1);
4431 geniCodeFunctionBody (tree,lvl);
4435 geniCodeReturn (right);
4439 geniCodeIfx (tree,lvl);
4443 geniCodeSwitch (tree,lvl);
4447 geniCodeInline (tree);
4451 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4455 geniCodeCritical (tree, lvl);
4461 /*-----------------------------------------------------------------*/
4462 /* reverseICChain - gets from the list and creates a linkedlist */
4463 /*-----------------------------------------------------------------*/
4470 while ((loop = getSet (&iCodeChain)))
4482 /*-----------------------------------------------------------------*/
4483 /* iCodeFromAst - given an ast will convert it to iCode */
4484 /*-----------------------------------------------------------------*/
4486 iCodeFromAst (ast * tree)
4488 returnLabel = newiTempLabel ("_return");
4489 entryLabel = newiTempLabel ("_entry");
4491 return reverseiCChain ();
4494 static const char *opTypeToStr(OPTYPE op)
4498 case SYMBOL: return "symbol";
4499 case VALUE: return "value";
4500 case TYPE: return "type";
4502 return "undefined type";
4506 operand *validateOpType(operand *op,
4513 if (op && op->type == type)
4518 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4519 " expected %s, got %s\n",
4520 macro, args, file, line,
4521 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4523 return op; // never reached, makes compiler happy.