Announce SDCC 4.5.0 RC3.
[sdcc.git] / sdcc / src / SDCCicode.c
bloba2413a3b8889568d87fa523f5f99801f5c1278ba
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
9 later version.
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 -------------------------------------------------------------------------*/
25 #include "common.h"
26 #include "newalloc.h"
27 #include "math.h"
28 #include "dbuf_string.h"
30 /*-----------------------------------------------------------------*/
31 /* global variables */
33 iCode *iCodeChain = 0;
34 iCode *iCodeChainEnd;
36 int iTempNum = 0;
37 int iTempLblNum = 0;
38 int operandKey = 0;
39 int iCodeKey = 0;
40 char *filename; /* current file name */
41 int lineno = 1; /* current line number */
42 int block;
43 long scopeLevel;
44 int seqPoint;
45 int inCriticalPair = 0;
46 int inlinedActive = 0;
48 symbol *returnLabel; /* function return label */
49 symbol *entryLabel; /* function entry label */
51 /*-----------------------------------------------------------------*/
52 /* forward definition of some functions */
53 operand *geniCodeAssign (operand *, operand *, int, int);
54 static operand *geniCodeArray (operand *, operand *, int, bool noderef);
55 static operand *geniCodeArray2Ptr (operand *);
56 operand *geniCodeRValue (operand *, bool);
57 operand *geniCodeDerefPtr (operand *, int);
58 static int isLvaluereq (int lvl);
59 static operand *geniCodeCast (sym_link *, operand *, bool);
61 #define PRINTFUNC(x) void x (struct dbuf_s *dbuf, const iCode *ic, char *s)
62 /* forward definition of ic print functions */
63 PRINTFUNC (picGetValueAtAddr);
64 PRINTFUNC (picPushValueAtAddr);
65 PRINTFUNC (picSetValueAtAddr);
66 PRINTFUNC (picAddrOf);
67 PRINTFUNC (picGeneric);
68 PRINTFUNC (picGenericOne);
69 PRINTFUNC (picCast);
70 PRINTFUNC (picAssign);
71 PRINTFUNC (picLabel);
72 PRINTFUNC (picGoto);
73 PRINTFUNC (picIfx);
74 PRINTFUNC (picJumpTable);
75 PRINTFUNC (picInline);
76 PRINTFUNC (picReceive);
77 PRINTFUNC (picDummyRead);
78 PRINTFUNC (picCritical);
79 PRINTFUNC (picEndCritical);
81 iCodeTable codeTable[] = {
82 {'!', "not", picGenericOne, NULL},
83 {'~', "~", picGenericOne, NULL},
84 {ROT, "rot", picGenericOne, NULL},
85 {GETABIT, "gabit", picGenericOne, NULL},
86 {GETBYTE, "gbyte", picGenericOne, NULL},
87 {GETWORD, "gword", picGenericOne, NULL},
88 {UNARYMINUS, "-", picGenericOne, NULL},
89 {IPUSH, "push", picGenericOne, NULL},
90 {IPUSH_VALUE_AT_ADDRESS, "push", picPushValueAtAddr, NULL},
91 {IPOP, "pop", picGenericOne, NULL},
92 {CALL, "call", picGenericOne, NULL},
93 {PCALL, "pcall", picGenericOne, NULL},
94 {FUNCTION, "proc", picGenericOne, NULL},
95 {ENDFUNCTION, "eproc", picGenericOne, NULL},
96 {RETURN, "ret", picGenericOne, NULL},
97 {'+', "+", picGeneric, NULL},
98 {'-', "-", picGeneric, NULL},
99 {'*', "*", picGeneric, NULL},
100 {'/', "/", picGeneric, NULL},
101 {'%', "%", picGeneric, NULL},
102 {'>', ">", picGeneric, NULL},
103 {'<', "<", picGeneric, NULL},
104 {LE_OP, "<=", picGeneric, NULL},
105 {GE_OP, ">=", picGeneric, NULL},
106 {EQ_OP, "==", picGeneric, NULL},
107 {NE_OP, "!=", picGeneric, NULL},
108 {AND_OP, "&&", picGeneric, NULL},
109 {OR_OP, "||", picGeneric, NULL},
110 {'^', "^", picGeneric, NULL},
111 {'|', "|", picGeneric, NULL},
112 {BITWISEAND, "&", picGeneric, NULL},
113 {LEFT_OP, "<<", picGeneric, NULL},
114 {RIGHT_OP, ">>", picGeneric, NULL},
115 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
116 {SET_VALUE_AT_ADDRESS, "@", picSetValueAtAddr, NULL},
117 {ADDRESS_OF, "&", picAddrOf, NULL},
118 {CAST, "<>", picCast, NULL},
119 {'=', ":=", picAssign, NULL},
120 {LABEL, "", picLabel, NULL},
121 {GOTO, "", picGoto, NULL},
122 {JUMPTABLE, "jtab", picJumpTable, NULL},
123 {IFX, "if", picIfx, NULL},
124 {INLINEASM, "", picInline, NULL},
125 {RECEIVE, "recv", picReceive, NULL},
126 {SEND, "send", picGenericOne, NULL},
127 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
128 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
129 {CRITICAL, "critical_start", picCritical, NULL},
130 {ENDCRITICAL, "critical_end", picEndCritical, NULL},
133 // ADDTOCHAIN - add iCode at the end of the chain. All-caps name, since this used to be a macro.
134 static void
135 ADDTOCHAIN (iCode *x)
137 if (!iCodeChain)
139 iCodeChain = x;
140 iCodeChainEnd = 0;
142 else
143 iCodeChainEnd->next = x;
145 x->prev = iCodeChainEnd;
146 iCodeChainEnd = x;
147 x->next = 0;
150 /*-----------------------------------------------------------------*/
151 /* operandName - returns the name of the operand */
152 /*-----------------------------------------------------------------*/
154 printOperand (operand * op, FILE * file)
156 struct dbuf_s dbuf;
157 int ret;
158 int pnl = 0;
160 if (!file)
162 file = stdout;
163 pnl = 1;
165 dbuf_init (&dbuf, 1024);
166 ret = dbuf_printOperand (op, &dbuf);
167 dbuf_write_and_destroy (&dbuf, file);
169 if (pnl)
170 putc ('\n', file);
172 return ret;
176 dbuf_printOperand (operand * op, struct dbuf_s *dbuf)
178 sym_link *opetype;
180 if (!op)
181 return 1;
183 switch (op->type)
185 case VALUE:
186 opetype = getSpec (operandType (op));
187 if (IS_FLOAT (opetype))
188 dbuf_printf (dbuf, "%g {", SPEC_CVAL (opetype).v_float);
189 else if (IS_FIXED16X16 (opetype))
190 dbuf_printf (dbuf, "%g {", doubleFromFixed16x16 (SPEC_CVAL (opetype).v_fixed16x16));
191 else if (IS_LONGLONG (opetype))
192 dbuf_printf (dbuf, "0x%llx {", (unsigned long long) SPEC_CVAL (OP_VALUE (op)->etype).v_ulonglong);
193 else
194 dbuf_printf (dbuf, "0x%x {", (unsigned int) ulFromVal (OP_VALUE (op)));
195 dbuf_printTypeChain (operandType (op), dbuf);
196 dbuf_append_char (dbuf, '}');
197 break;
199 case SYMBOL:
200 #define REGA 1
201 //#if REGA /* { */
202 if (REGA && !getenv ("PRINT_SHORT_OPERANDS"))
204 dbuf_printf (dbuf, "%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}" , */
205 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
206 op->key,
207 OP_LIVEFROM (op), OP_LIVETO (op),
208 OP_SYMBOL (op)->stack,
209 op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
210 OP_SYMBOL (op)->remat, OP_SYMBOL (op)->noSpilLoc, OP_SYMBOL (op)->ruonly, OP_SYMBOL (op)->dptr);
212 dbuf_append_char (dbuf, '{');
213 dbuf_printTypeChain (operandType (op), dbuf);
214 if (SPIL_LOC (op) && IS_ITEMP (op))
215 dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
216 dbuf_append_char (dbuf, '}');
219 /* if assigned to registers */
220 if (OP_SYMBOL (op)->nRegs)
222 bool completely_spilt = OP_SYMBOL (op)->isspilt;
223 for (int i = 0; i < OP_SYMBOL (op)->nRegs; i++)
224 if (OP_SYMBOL (op)->regs[i])
225 completely_spilt = false;
226 if (completely_spilt)
228 if (!OP_SYMBOL (op)->remat)
229 if (OP_SYMBOL (op)->usl.spillLoc)
230 dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
231 OP_SYMBOL (op)->usl.spillLoc->rname : OP_SYMBOL (op)->usl.spillLoc->name));
232 else
233 dbuf_append_str (dbuf, "[err]");
234 else
235 dbuf_append_str (dbuf, "[remat]");
237 else
239 dbuf_append_char (dbuf, '[');
240 for (int i = 0; i < OP_SYMBOL (op)->nRegs; i++)
242 if (OP_SYMBOL (op)->regs[i]) // A byte in a register.
243 dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
244 else // A spilt byte in an operand that has been partially assigned to registers, partially spilt.
245 if (OP_SYMBOL (op)->usl.spillLoc)
246 dbuf_printf (dbuf, "%s ", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
247 OP_SYMBOL (op)->usl.spillLoc->rname : OP_SYMBOL (op)->usl.spillLoc->name));
248 else
249 dbuf_append_str (dbuf, "[err]");
252 dbuf_append_char (dbuf, ']');
255 //#else /* } else { */
257 else
259 /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
260 dbuf_printf (dbuf, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
262 if (getenv ("PRINT_SHORT_OPERANDS")[0] < '1')
264 dbuf_printf (dbuf, "[lr%d:%d so:%d]", OP_LIVEFROM (op), OP_LIVETO (op), OP_SYMBOL (op)->stack);
267 if (getenv ("PRINT_SHORT_OPERANDS")[0] < '2')
269 dbuf_append_char (dbuf, '{');
270 dbuf_printTypeChain (operandType (op), dbuf);
271 if (SPIL_LOC (op) && IS_ITEMP (op))
272 dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
273 dbuf_append_char (dbuf, '}');
276 /* if assigned to registers */
277 if (OP_SYMBOL (op)->nRegs)
279 if (OP_SYMBOL (op)->isspilt)
281 if (!OP_SYMBOL (op)->remat)
282 if (OP_SYMBOL (op)->usl.spillLoc)
283 dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
284 OP_SYMBOL (op)->usl.spillLoc->rname : OP_SYMBOL (op)->usl.spillLoc->name));
285 else
286 dbuf_append_str (dbuf, "[err]");
287 else
288 dbuf_append_str (dbuf, "[remat]");
290 else
292 int i;
293 dbuf_append_char (dbuf, '[');
294 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
295 dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
296 dbuf_append_char (dbuf, ']');
299 //#endif /* } */
301 break;
303 case TYPE:
304 dbuf_append_char (dbuf, '(');
305 dbuf_printTypeChain (OP_TYPE (op), dbuf);
306 dbuf_append_char (dbuf, ')');
307 break;
310 return 0;
314 /*-----------------------------------------------------------------*/
315 /* print functions */
316 /*-----------------------------------------------------------------*/
317 PRINTFUNC (picGetValueAtAddr)
319 dbuf_append_char (dbuf, '\t');
320 dbuf_printOperand (IC_RESULT (ic), dbuf);
321 dbuf_append_str (dbuf, " = ");
322 dbuf_append_str (dbuf, "@[");
323 dbuf_printOperand (IC_LEFT (ic), dbuf);
324 if (IC_RIGHT (ic))
326 dbuf_append_str (dbuf, " + ");
327 dbuf_printOperand (IC_RIGHT (ic), dbuf);
329 dbuf_append_str (dbuf, "]\n");
332 PRINTFUNC (picPushValueAtAddr)
334 dbuf_append_char (dbuf, '\t');
335 dbuf_append_str (dbuf, "push ");
336 dbuf_append_str (dbuf, "@[");
337 dbuf_printOperand (IC_LEFT (ic), dbuf);
338 if (IC_RIGHT (ic))
340 dbuf_append_str (dbuf, " + ");
341 dbuf_printOperand (IC_RIGHT (ic), dbuf);
343 dbuf_append_str (dbuf, "]\n");
346 PRINTFUNC (picSetValueAtAddr)
348 dbuf_append_char (dbuf, '\t');
349 dbuf_append_str (dbuf, "*[");
350 dbuf_printOperand (IC_LEFT (ic), dbuf);
351 dbuf_append_str (dbuf, "] = ");
352 dbuf_printOperand (IC_RIGHT (ic), dbuf);
353 dbuf_append_char (dbuf, '\n');
356 PRINTFUNC (picAddrOf)
358 dbuf_append_char (dbuf, '\t');
359 dbuf_printOperand (IC_RESULT (ic), dbuf);
360 if (IS_ITEMP (IC_LEFT (ic)))
361 dbuf_append_str (dbuf, " = ");
362 else
363 dbuf_append_str (dbuf, " = &[");
364 dbuf_printOperand (IC_LEFT (ic), dbuf);
365 if (IC_RIGHT (ic))
367 if (IS_ITEMP (IC_LEFT (ic)))
368 dbuf_append_str (dbuf, " offsetAdd ");
369 else
370 dbuf_append_str (dbuf, " , ");
371 dbuf_printOperand (IC_RIGHT (ic), dbuf);
373 if (IS_ITEMP (IC_LEFT (ic)))
374 dbuf_append_char (dbuf, '\n');
375 else
376 dbuf_append_str (dbuf, "]\n");
379 PRINTFUNC (picJumpTable)
381 symbol *sym;
383 dbuf_append_char (dbuf, '\t');
384 dbuf_printf (dbuf, "%s\t", s);
385 dbuf_printOperand (IC_JTCOND (ic), dbuf);
386 for (sym = setFirstItem (IC_JTLABELS (ic)); sym; sym = setNextItem (IC_JTLABELS (ic)))
387 dbuf_printf (dbuf, "; %s", sym->name);
388 dbuf_append_char (dbuf, '\n');
391 PRINTFUNC (picGeneric)
393 dbuf_append_char (dbuf, '\t');
394 dbuf_printOperand (IC_RESULT (ic), dbuf);
395 dbuf_append_str (dbuf, " = ");
396 dbuf_printOperand (IC_LEFT (ic), dbuf);
397 dbuf_printf (dbuf, " %s ", s);
398 dbuf_printOperand (IC_RIGHT (ic), dbuf);
399 dbuf_append_char (dbuf, '\n');
402 PRINTFUNC (picGenericOne)
404 dbuf_append_char (dbuf, '\t');
405 if (IC_RESULT (ic))
407 dbuf_printOperand (IC_RESULT (ic), dbuf);
408 dbuf_append_str (dbuf, " = ");
411 if (IC_LEFT (ic))
413 dbuf_printf (dbuf, "%s ", s);
414 dbuf_printOperand (IC_LEFT (ic), dbuf);
417 if (!IC_RESULT (ic) && !IC_LEFT (ic))
418 dbuf_append_str (dbuf, s);
420 if (ic->op == SEND || ic->op == RECEIVE)
422 dbuf_printf (dbuf, "{argreg = %d}", ic->argreg);
424 if (ic->op == IPUSH)
426 dbuf_printf (dbuf, "{parmPush = %d}", ic->parmPush);
428 dbuf_append_char (dbuf, '\n');
431 PRINTFUNC (picCast)
433 dbuf_append_char (dbuf, '\t');
434 dbuf_printOperand (IC_RESULT (ic), dbuf);
435 dbuf_append_str (dbuf, " = ");
436 dbuf_printOperand (IC_LEFT (ic), dbuf);
437 dbuf_printOperand (IC_RIGHT (ic), dbuf);
438 dbuf_append_char (dbuf, '\n');
442 PRINTFUNC (picAssign)
444 dbuf_append_char (dbuf, '\t');
446 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
447 dbuf_append_str (dbuf, "*(");
449 dbuf_printOperand (IC_RESULT (ic), dbuf);
451 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
452 dbuf_append_char (dbuf, ')');
454 dbuf_printf (dbuf, " %s ", s);
455 dbuf_printOperand (IC_RIGHT (ic), dbuf);
457 dbuf_append_char (dbuf, '\n');
460 PRINTFUNC (picLabel)
462 dbuf_printf (dbuf, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
465 PRINTFUNC (picGoto)
467 dbuf_append_char (dbuf, '\t');
468 dbuf_printf (dbuf, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
471 PRINTFUNC (picIfx)
473 dbuf_append_char (dbuf, '\t');
474 dbuf_append_str (dbuf, "if ");
475 dbuf_printOperand (IC_COND (ic), dbuf);
477 if (!IC_TRUE (ic))
478 dbuf_printf (dbuf, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
479 else
481 dbuf_printf (dbuf, " != 0 goto %s($%d)", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
482 if (IC_FALSE (ic))
483 dbuf_printf (dbuf, "; zzgoto %s\n", IC_FALSE (ic)->name);
484 dbuf_append_char (dbuf, '\n');
488 PRINTFUNC (picInline)
490 dbuf_append_str (dbuf, IC_INLINE (ic));
493 PRINTFUNC (picReceive)
495 dbuf_printOperand (IC_RESULT (ic), dbuf);
496 dbuf_printf (dbuf, " = %s ", s);
497 dbuf_printOperand (IC_LEFT (ic), dbuf);
498 dbuf_append_char (dbuf, '\n');
501 PRINTFUNC (picDummyRead)
503 dbuf_append_char (dbuf, '\t');
504 dbuf_printf (dbuf, "%s ", s);
505 dbuf_printOperand (IC_RIGHT (ic), dbuf);
506 dbuf_append_char (dbuf, '\n');
509 PRINTFUNC (picCritical)
511 dbuf_append_char (dbuf, '\t');
512 if (IC_RESULT (ic))
513 dbuf_printOperand (IC_RESULT (ic), dbuf);
514 else
515 dbuf_append_str (dbuf, "(stack)");
516 dbuf_printf (dbuf, " = %s ", s);
517 dbuf_append_char (dbuf, '\n');
520 PRINTFUNC (picEndCritical)
522 dbuf_append_char (dbuf, '\t');
523 dbuf_printf (dbuf, "%s = ", s);
524 if (IC_RIGHT (ic))
525 dbuf_printOperand (IC_RIGHT (ic), dbuf);
526 else
527 dbuf_append_str (dbuf, "(stack)");
528 dbuf_append_char (dbuf, '\n');
531 /*-----------------------------------------------------------------*/
532 /* piCode - prints one iCode */
533 /*-----------------------------------------------------------------*/
535 piCode (const iCode * ic, FILE * of)
537 iCodeTable *icTab;
538 struct dbuf_s dbuf;
540 if (!of)
541 of = stdout;
543 icTab = getTableEntry (ic->op);
544 fprintf (of, "%s(%d:%d:%d:%d:%d:%d)\t", ic->filename, ic->lineno, ic->seq, ic->key, ic->depth, ic->supportRtn, ic->block);
545 dbuf_init (&dbuf, 1024);
546 icTab->iCodePrint (&dbuf, ic, icTab->printName);
547 dbuf_write_and_destroy (&dbuf, of);
548 return 1;
551 void
552 PICC (iCode * ic)
554 printiCChain (ic, stdout);
557 /*-----------------------------------------------------------------*/
558 /* printiCChain - prints intermediate code for humans */
559 /*-----------------------------------------------------------------*/
560 void
561 printiCChain (iCode * icChain, FILE * of)
563 iCode *loop;
564 iCodeTable *icTab;
566 if (!of)
567 of = stdout;
568 for (loop = icChain; loop; loop = loop->next)
570 if ((icTab = getTableEntry (loop->op)))
572 struct dbuf_s dbuf;
574 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d:b%d)\t",
575 loop->filename, loop->lineno, loop->seq, loop->key, loop->depth, loop->supportRtn, loop->block);
577 dbuf_init (&dbuf, 1024);
578 icTab->iCodePrint (&dbuf, loop, icTab->printName);
579 dbuf_write_and_destroy (&dbuf, of);
581 fflush (of);
587 /*-----------------------------------------------------------------*/
588 /* newOperand - allocate, init & return a new iCode */
589 /*-----------------------------------------------------------------*/
590 operand *
591 newOperand ()
593 operand *op;
595 op = Safe_alloc (sizeof (operand));
597 op->key = 0;
598 return op;
601 /*-----------------------------------------------------------------*/
602 /* newiCode - create and return a new iCode entry initialized */
603 /*-----------------------------------------------------------------*/
604 iCode *
605 newiCode (int op, operand *left, operand *right)
607 iCode *ic;
609 ic = Safe_alloc (sizeof (iCode));
611 ic->seqPoint = seqPoint;
612 ic->filename = filename;
613 ic->lineno = lineno;
614 ic->block = block;
615 ic->level = scopeLevel;
616 ic->op = op;
617 ic->key = iCodeKey++;
618 IC_LEFT (ic) = left;
619 IC_RIGHT (ic) = right;
620 ic->inlined = inlinedActive;
622 // Err on the save side for now, setting this to false later is up to later analysis.
623 ic->localEscapeAlive = true;
624 ic->parmEscapeAlive = true;
626 ic->valinfos = 0;
627 ic->resultvalinfo = 0;
629 return ic;
632 /*-----------------------------------------------------------------*/
633 /* newiCode for conditional statements */
634 /*-----------------------------------------------------------------*/
635 iCode *
636 newiCodeCondition (operand * condition, symbol * trueLabel, symbol * falseLabel)
638 iCode *ic;
640 if (IS_VOID (operandType (condition)))
642 werror (E_VOID_VALUE_USED);
645 ic = newiCode (IFX, NULL, NULL);
646 IC_COND (ic) = condition;
647 IC_TRUE (ic) = trueLabel;
648 IC_FALSE (ic) = falseLabel;
649 return ic;
652 /*-----------------------------------------------------------------*/
653 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
654 /*-----------------------------------------------------------------*/
655 iCode *
656 newiCodeLabelGoto (int op, symbol * label)
658 iCode *ic;
660 ic = newiCode (op, NULL, NULL);
661 ic->op = op;
662 ic->label = label;
663 IC_LEFT (ic) = NULL;
664 IC_RIGHT (ic) = NULL;
665 IC_RESULT (ic) = NULL;
666 return ic;
669 /*-----------------------------------------------------------------*/
670 /* newiTemp - allocate & return a newItemp Variable */
671 /*-----------------------------------------------------------------*/
672 symbol *
673 newiTemp (const char *s)
675 struct dbuf_s dbuf;
676 symbol *itmp;
678 dbuf_init (&dbuf, 128);
679 if (s)
680 dbuf_append_str (&dbuf, s);
681 else
682 dbuf_printf (&dbuf, "iTemp%d", iTempNum++);
684 itmp = newSymbol (dbuf_c_str (&dbuf), 1);
685 dbuf_destroy (&dbuf);
686 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
687 itmp->isitmp = 1;
689 return itmp;
692 /*-----------------------------------------------------------------*/
693 /* newiTempLabel - creates a temp variable label */
694 /*-----------------------------------------------------------------*/
695 symbol *
696 newiTempLabel (const char *s)
698 symbol *itmplbl;
700 /* check if this already exists */
701 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
702 return itmplbl;
704 if (s)
706 itmplbl = newSymbol (s, 1);
708 else
710 struct dbuf_s dbuf;
712 dbuf_init (&dbuf, 128);
713 dbuf_printf (&dbuf, "iTempLbl%d", iTempLblNum++);
714 itmplbl = newSymbol (dbuf_c_str (&dbuf), 1);
715 dbuf_destroy (&dbuf);
718 itmplbl->isitmp = 1;
719 itmplbl->islbl = 1;
720 itmplbl->key = labelKey++;
721 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
722 return itmplbl;
725 /*-----------------------------------------------------------------*/
726 /* newiTempLoopHeaderLabel - creates a new loop header label */
727 /*-----------------------------------------------------------------*/
728 symbol *
729 newiTempLoopHeaderLabel (bool pre)
731 symbol *itmplbl;
732 struct dbuf_s dbuf;
734 dbuf_init (&dbuf, 128);
735 dbuf_printf (&dbuf, pre ? "preHeaderLbl%d" : LOOPEXITLBL "%d", iTempLblNum++);
736 itmplbl = newSymbol (dbuf_c_str (&dbuf), 1);
737 dbuf_destroy (&dbuf);
739 itmplbl->isitmp = 1;
740 itmplbl->islbl = 1;
741 itmplbl->key = labelKey++;
742 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
743 return itmplbl;
747 /*-----------------------------------------------------------------*/
748 /* initiCode - initializes some iCode related stuff */
749 /*-----------------------------------------------------------------*/
750 void
751 initiCode ()
756 /*-----------------------------------------------------------------*/
757 /* copyiCode - make a copy of the iCode given */
758 /*-----------------------------------------------------------------*/
759 iCode *
760 copyiCode (iCode * ic)
762 iCode *nic = newiCode (ic->op, NULL, NULL);
764 nic->filename = ic->filename;
765 nic->lineno = ic->lineno;
766 nic->block = ic->block;
767 nic->level = ic->level;
768 nic->parmBytes = ic->parmBytes;
770 /* deal with the special cases first */
771 switch (ic->op)
773 case IFX:
774 IC_COND (nic) = operandFromOperand (IC_COND (ic));
775 IC_TRUE (nic) = IC_TRUE (ic);
776 IC_FALSE (nic) = IC_FALSE (ic);
777 break;
779 case JUMPTABLE:
780 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
781 IC_JTLABELS (nic) = IC_JTLABELS (ic);
782 break;
784 case CALL:
785 case PCALL:
786 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
787 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
788 break;
790 case INLINEASM:
791 IC_INLINE (nic) = IC_INLINE (ic);
792 break;
794 case ARRAYINIT:
795 IC_ARRAYILIST (nic) = IC_ARRAYILIST (ic);
796 break;
798 default:
799 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
800 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
801 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
804 return nic;
807 /*-----------------------------------------------------------------*/
808 /* getTableEntry - gets the table entry for the given operator */
809 /*-----------------------------------------------------------------*/
810 iCodeTable *
811 getTableEntry (int oper)
813 unsigned i;
815 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
816 if (oper == codeTable[i].icode)
817 return &codeTable[i];
819 return NULL;
822 /*-----------------------------------------------------------------*/
823 /* newiTempOperand - new intermediate temp operand */
824 /*-----------------------------------------------------------------*/
825 operand *
826 newiTempOperand (sym_link * type, char throwType)
828 symbol *itmp;
829 operand *op = newOperand ();
830 sym_link *etype;
832 op->type = SYMBOL;
833 itmp = newiTemp (NULL);
835 etype = getSpec (type);
837 if (IS_LITERAL (etype))
838 throwType = 0;
840 /* copy the type information */
841 if (type)
842 itmp->etype = getSpec (itmp->type = (throwType ? type : copyLinkChain (type)));
844 SPEC_SCLS (itmp->etype) = S_FIXED;
846 /* iTemps always live in the default address space */
847 if (IS_DECL (itmp->type))
848 DCL_PTR_ADDRSPACE (itmp->type) = 0;
849 else
850 SPEC_ADDRSPACE (itmp->etype) = 0;
852 op->svt.symOperand = itmp;
853 op->key = itmp->key = ++operandKey;
854 return op;
857 /*-----------------------------------------------------------------*/
858 /* operandType - returns the type chain for an operand */
859 /*-----------------------------------------------------------------*/
860 sym_link *
861 operandType (const operand *op)
863 wassert (op);
865 /* depending on type of operand */
866 switch (op->type)
868 case VALUE:
869 return op->svt.valOperand->type;
871 case SYMBOL:
872 return op->svt.symOperand->type;
874 case TYPE:
875 return op->svt.typeOperand;
877 default:
878 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, " operand type not known ");
879 assert (0); /* should never come here */
880 /* Just to keep the compiler happy */
881 return (sym_link *) 0;
885 /*-----------------------------------------------------------------*/
886 /* operandSize - returns size of an operand in bytes */
887 /*-----------------------------------------------------------------*/
888 unsigned int
889 operandSize (operand * op)
891 sym_link *type;
893 /* if nothing return 0 */
894 if (!op)
895 return 0;
897 type = operandType (op);
898 if (op->aggr2ptr == 2)
899 type = type->next;
900 return getSize (type);
903 /*-----------------------------------------------------------------*/
904 /* isParamterToCall - will return 1 if op is a parameter to args */
905 /*-----------------------------------------------------------------*/
907 isParameterToCall (value * args, operand * op)
909 value *tval = args;
911 wassert (IS_SYMOP (op));
913 while (tval)
915 if (tval->sym && isSymbolEqual (OP_SYMBOL (op), tval->sym))
916 return 1;
917 tval = tval->next;
919 return 0;
922 /*-----------------------------------------------------------------*/
923 /* isOperandGlobal - return 1 if operand is a global variable */
924 /*-----------------------------------------------------------------*/
926 isOperandGlobal (const operand *op)
928 if (!op)
929 return 0;
931 if (IS_ITEMP (op))
932 return 0;
934 if (IS_SYMOP (op) &&
935 (op->svt.symOperand->level == 0 || IS_STATIC (op->svt.symOperand->etype) || IS_EXTERN (op->svt.symOperand->etype)))
936 return 1;
938 return 0;
941 /*-----------------------------------------------------------------*/
942 /* isOperandVolatile - return 1 if the operand is volatile */
943 /*-----------------------------------------------------------------*/
945 isOperandVolatile (const operand *op, bool chkTemp)
947 if (!op)
948 return 0;
950 if (IS_ITEMP (op) && !chkTemp)
951 return 0;
953 return IS_VOLATILE (operandType (op));
956 /*-----------------------------------------------------------------*/
957 /* isOperandLiteral - returns 1 if an operand contains a literal */
958 /*-----------------------------------------------------------------*/
960 isOperandLiteral (const operand *const op)
962 sym_link *opetype;
964 if (!op)
965 return 0;
967 opetype = getSpec (operandType (op));
969 if (IS_LITERAL (opetype))
970 return 1;
972 return 0;
975 /*-----------------------------------------------------------------*/
976 /* isOperandInFarSpace - will return true if operand is in farSpace */
977 /*-----------------------------------------------------------------*/
978 bool
979 isOperandInFarSpace (operand * op)
981 sym_link *etype;
983 if (!op)
984 return FALSE;
986 if (!IS_SYMOP (op))
987 return FALSE;
989 if (!IS_TRUE_SYMOP (op))
991 if (SPIL_LOC (op))
992 etype = SPIL_LOC (op)->etype;
993 else
994 return FALSE;
996 else
998 etype = getSpec (operandType (op));
1000 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1003 /*-----------------------------------------------------------------*/
1004 /* isOperandInPagedSpace - return true if operand is in pagedSpace */
1005 /*-----------------------------------------------------------------*/
1006 bool
1007 isOperandInPagedSpace (operand * op)
1009 sym_link *etype;
1011 if (!op)
1012 return FALSE;
1014 if (!IS_SYMOP (op))
1015 return FALSE;
1017 if (!IS_TRUE_SYMOP (op))
1019 if (SPIL_LOC (op))
1020 etype = SPIL_LOC (op)->etype;
1021 else
1022 return FALSE;
1024 else
1026 etype = getSpec (operandType (op));
1028 return (IN_PAGEDSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1031 /*------------------------------------------------------------------*/
1032 /* isOperandInDirSpace - will return true if operand is in dirSpace */
1033 /*------------------------------------------------------------------*/
1034 bool
1035 isOperandInDirSpace (operand * op)
1037 sym_link *etype;
1039 if (!op)
1040 return FALSE;
1042 if (!IS_SYMOP (op))
1043 return FALSE;
1045 if (!IS_TRUE_SYMOP (op))
1047 if (SPIL_LOC (op))
1048 etype = SPIL_LOC (op)->etype;
1049 else
1050 return FALSE;
1052 else
1054 etype = getSpec (operandType (op));
1056 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1059 /*-----------------------------------------------------------------*/
1060 /* isOperandInBitSpace - will return true if operand is in bitSpace */
1061 /*-----------------------------------------------------------------*/
1062 bool
1063 isOperandInBitSpace (operand * op)
1065 sym_link *etype;
1067 if (!op)
1068 return FALSE;
1070 if (!IS_SYMOP (op))
1071 return FALSE;
1073 if (!IS_TRUE_SYMOP (op))
1075 if (SPIL_LOC (op))
1076 etype = SPIL_LOC (op)->etype;
1077 else
1078 return FALSE;
1080 else
1082 etype = getSpec (operandType (op));
1084 return (IN_BITSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1087 /*--------------------------------------------------------------------*/
1088 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
1089 /*--------------------------------------------------------------------*/
1090 bool
1091 isOperandInCodeSpace (operand * op)
1093 sym_link *etype;
1095 if (!op)
1096 return FALSE;
1098 if (!IS_SYMOP (op))
1099 return FALSE;
1101 etype = getSpec (operandType (op));
1103 if (!IS_TRUE_SYMOP (op))
1105 if (SPIL_LOC (op))
1106 etype = SPIL_LOC (op)->etype;
1107 else
1108 return FALSE;
1110 else
1112 etype = getSpec (operandType (op));
1114 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1117 /*-----------------------------------------------------------------*/
1118 /* isOperandOnStack - will return true if operand is on stack */
1119 /*-----------------------------------------------------------------*/
1120 bool
1121 isOperandOnStack (operand * op)
1123 sym_link *etype;
1125 if (!op)
1126 return FALSE;
1128 if (!IS_SYMOP (op))
1129 return FALSE;
1131 etype = getSpec (operandType (op));
1132 if (IN_STACK (etype) || OP_SYMBOL (op)->onStack || (SPIL_LOC (op) && SPIL_LOC (op)->onStack))
1133 return TRUE;
1135 return FALSE;
1139 /*-------------------------------------------------------------------*/
1140 /* detachiCodeOperand - remove a specific operand position (left, */
1141 /* right, result) from an iCode and update */
1142 /* the uses & defs as appropriate. */
1143 /*-------------------------------------------------------------------*/
1144 operand *
1145 detachiCodeOperand (operand **opp, iCode *ic)
1147 operand *op = *opp;
1149 if (IS_SYMOP (op))
1151 int uses = 0;
1152 bool ispointerset = POINTER_SET (ic);
1154 if (!ispointerset && (opp == &ic->result))
1155 bitVectUnSetBit (OP_DEFS (op), ic->key);
1156 *opp = NULL;
1157 if (ispointerset && (op == ic->result))
1158 uses++;
1159 if (op == ic->left)
1160 uses++;
1161 if (op == ic->right)
1162 uses++;
1163 if (uses == 0)
1164 bitVectUnSetBit (OP_USES (op), ic->key);
1166 else
1167 *opp = NULL;
1168 return op;
1171 /*-------------------------------------------------------------------*/
1172 /* attachiCodeOperand - insert an operand to a specific operand */
1173 /* position (left, right, result) in an */
1174 /* iCode and update the uses & defs as */
1175 /* appropriate. Any previously existing operand */
1176 /* in that position will be detached first. */
1177 /*-------------------------------------------------------------------*/
1178 void
1179 attachiCodeOperand (operand *newop, operand **opp, iCode *ic)
1181 /* If there is already an operand here, detach it first */
1182 if (*opp)
1183 detachiCodeOperand (opp, ic);
1185 /* Insert new operand */
1186 *opp = newop;
1188 /* Update defs/uses for new operand */
1189 if (IS_SYMOP (newop))
1191 if (opp == &ic->result && !POINTER_SET (ic))
1192 OP_DEFS (newop) = bitVectSetBit (OP_DEFS (newop), ic->key);
1193 else
1194 OP_USES (newop) = bitVectSetBit (OP_USES (newop), ic->key);
1200 /*-----------------------------------------------------------------*/
1201 /* isOclsExpensive - will return true if accesses to an output */
1202 /* storage class are expensive */
1203 /*-----------------------------------------------------------------*/
1204 bool
1205 isOclsExpensive (struct memmap * oclass)
1207 if (port->oclsExpense)
1208 return port->oclsExpense (oclass) > 0;
1210 /* In the absence of port specific guidance, assume only */
1211 /* farspace is expensive. */
1212 return IN_FARSPACE (oclass);
1215 /*-----------------------------------------------------------------*/
1216 /* isiCodeInFunctionCall - return TRUE if an iCode is between a */
1217 /* CALL/PCALL and the first IPUSH/SEND associated with the call */
1218 /*-----------------------------------------------------------------*/
1220 isiCodeInFunctionCall (iCode * ic)
1222 iCode *lic = ic;
1224 /* Find the next CALL/PCALL */
1225 while (lic)
1227 if (lic->op == CALL || lic->op == PCALL)
1228 break;
1229 lic = lic->next;
1232 if (!lic)
1233 return FALSE;
1235 /* A function call was found. Scan backwards and see if an */
1236 /* IPUSH or SEND is encountered */
1237 while (ic)
1239 if (lic != ic && (ic->op == CALL || ic->op == PCALL))
1240 return FALSE;
1241 if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
1242 return TRUE;
1243 ic = ic->prev;
1246 return FALSE;
1249 /*-----------------------------------------------------------------*/
1250 /* operandLitValueUll - unsigned long long value of an operand */
1251 /*-----------------------------------------------------------------*/
1252 unsigned long long
1253 operandLitValueUll (const operand * op)
1255 assert (isOperandLiteral (op));
1257 return ullFromVal (OP_VALUE_CONST (op));
1260 /*-----------------------------------------------------------------*/
1261 /* operandLitValue - literal value of an operand */
1262 /*-----------------------------------------------------------------*/
1263 double
1264 operandLitValue (const operand * op)
1266 assert (isOperandLiteral (op));
1268 return floatFromVal (OP_VALUE_CONST (op));
1271 extern bool regalloc_dry_run;
1273 /*-----------------------------------------------------------------*/
1274 /* getBuiltInParms - returns parameters to a builtin function */
1275 /*-----------------------------------------------------------------*/
1276 iCode *
1277 getBuiltinParms (iCode * fic, int *pcount, operand ** parms)
1279 sym_link *ftype;
1280 iCode *ic = fic;
1282 *pcount = 0;
1283 /* builtin function uses only SEND for parameters */
1284 while (ic->op != CALL)
1286 assert (ic->op == SEND && ic->builtinSEND);
1287 if(!regalloc_dry_run || ic != fic)
1288 ic->generated = 1; /* mark the icode as generated */
1289 parms[*pcount] = IC_LEFT (ic);
1290 ic = ic->next;
1291 (*pcount)++;
1294 ic->generated = 1;
1295 /* make sure this is a builtin function call */
1296 assert (IS_SYMOP (IC_LEFT (ic)));
1297 ftype = operandType (IC_LEFT (ic));
1298 assert (IFFUNC_ISBUILTIN (ftype));
1299 return ic;
1302 /*-----------------------------------------------------------------*/
1303 /* operandOperation - performs operations on operands */
1304 /*-----------------------------------------------------------------*/
1305 operand *
1306 operandOperation (operand * left, operand * right, int op, sym_link * type)
1308 sym_link *let, *ret = NULL;
1309 operand *retval = (operand *) 0;
1311 assert (isOperandLiteral (left));
1312 let = getSpec (operandType (left));
1313 if (right)
1315 assert (isOperandLiteral (right));
1316 ret = getSpec (operandType (right));
1319 /* FIXME: most of these are not long long safe yet */
1320 switch (op)
1322 case '+':
1323 retval = operandFromValue (valCastLiteral (type, operandLitValue (left) + operandLitValue (right), operandLitValueUll (left) + operandLitValueUll (right)), false);
1324 break;
1325 case '-':
1326 retval = operandFromValue (valCastLiteral (type, operandLitValue (left) - operandLitValue (right), operandLitValueUll (left) - operandLitValueUll (right)), false);
1327 break;
1328 case '*':
1330 retval = operandFromValue (valCastLiteral (type,
1331 operandLitValue (left) *
1332 operandLitValue (right)));
1333 This could be all we've to do, but with gcc we've to take care about
1334 overflows. Two examples:
1335 ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1336 significant bits are lost (52 in fraction, 63 bits would be
1337 necessary to keep full precision).
1338 If the resulting double value is greater than ULONG_MAX (resp.
1339 USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1342 /* if it is not a specifier then we can assume that */
1343 /* it will be an unsigned long */
1344 if (IS_INT (type) || !IS_SPEC (type))
1346 /* long long is handled here, because it can overflow with double */
1347 if (IS_LONGLONG (type) || !IS_SPEC (type))
1348 /* signed and unsigned mul are the same, as long as the precision
1349 of the result isn't bigger than the precision of the operands. */
1350 retval = operandFromValue (valCastLiteral (type,
1351 operandLitValue (left) *
1352 operandLitValue (right),
1353 operandLitValueUll (left) *
1354 operandLitValueUll (right)), false);
1355 /* long is handled here, because it can overflow with double */
1356 else if (IS_LONG (type) || !IS_SPEC (type))
1357 /* signed and unsigned mul are the same, as long as the precision
1358 of the result isn't bigger than the precision of the operands. */
1359 retval = operandFromValue (valCastLiteral (type,
1360 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) *
1361 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)),
1362 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) *
1363 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))), false);
1364 else if (IS_UNSIGNED (type)) /* unsigned int */
1366 /* unsigned int is handled here in order to detect overflow */
1367 TYPE_TARGET_ULONG ul = (TYPE_TARGET_UINT) double2ul (operandLitValue (left)) *
1368 (TYPE_TARGET_UINT) double2ul (operandLitValue (right));
1370 retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_UINT) ul, (TYPE_TARGET_UINT) ul), false);
1371 if (ul != (TYPE_TARGET_UINT) ul)
1372 werror (W_INT_OVL);
1374 else /* signed int */
1376 /* signed int is handled here in order to detect overflow */
1377 TYPE_TARGET_LONG l = (TYPE_TARGET_INT) operandLitValue (left) * (TYPE_TARGET_INT) operandLitValue (right);
1379 retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_INT) l, (TYPE_TARGET_INT) l), false);
1380 if (l != (TYPE_TARGET_INT) l)
1381 werror (W_INT_OVL);
1384 else
1385 /* all others go here: */
1386 retval = operandFromValue (valCastLiteral (type, operandLitValue (left) * operandLitValue (right), operandLitValueUll (left) * operandLitValueUll (right)), false);
1387 break;
1388 case '/':
1389 if (!IS_FLOAT (operandType (right)) && (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0 && operandLitValueUll (right) == 0)
1391 werror (E_DIVIDE_BY_ZERO);
1392 retval = right;
1393 break;
1395 if (IS_UNSIGNED (type))
1397 SPEC_USIGN (let) = 1;
1398 SPEC_USIGN (ret) = 1;
1399 if (IS_LONGLONG (type))
1400 retval = operandFromValue (valCastLiteral (type,
1401 0.0,
1402 operandLitValueUll (left) /
1403 operandLitValueUll (right)), false);
1404 else
1405 retval = operandFromValue (valCastLiteral (type,
1406 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) /
1407 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)),
1408 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) /
1409 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))), false);
1411 else
1413 if (IS_FLOAT (operandType (right))) // Avoid division by 0 for right operand close to 0.
1414 retval = operandFromValue (valCastLiteral (type, operandLitValue (left) / operandLitValue (right), operandLitValue (left) / operandLitValue (right)), false);
1415 else
1416 retval = operandFromValue (valCastLiteral (type, operandLitValue (left) / operandLitValue (right), operandLitValueUll (left) / operandLitValueUll (right)), false);
1418 break;
1419 case '%':
1420 if ((TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0 && operandLitValueUll (right) == 0)
1422 werror (E_DIVIDE_BY_ZERO);
1423 retval = right;
1425 else
1427 if (IS_UNSIGNED (type))
1429 if (IS_LONGLONG (type))
1430 retval = operandFromValue (valCastLiteral (type,
1431 0.0,
1432 operandLitValueUll (left) %
1433 operandLitValueUll (right)), false);
1434 else
1435 retval = operandFromLit ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) % (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)));
1437 else
1438 retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) % (TYPE_TARGET_LONG) operandLitValue (right));
1440 break;
1441 case LEFT_OP:
1442 /* The number of left shifts is always unsigned. Signed doesn't make
1443 sense here. Shifting by a negative number is impossible. */
1444 if (IS_LONGLONG (type))
1445 retval = operandFromValue (valCastLiteral (type,
1446 (operandLitValueUll (left) <<
1447 operandLitValueUll (right)),
1448 (operandLitValueUll (left) <<
1449 operandLitValueUll (right))), false);
1450 else
1451 retval = operandFromValue (valCastLiteral (type,
1452 ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) <<
1453 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))),
1454 ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) <<
1455 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)))), false);
1456 break;
1457 case RIGHT_OP:
1458 /* The number of right shifts is always unsigned. Signed doesn't make
1459 sense here. Shifting by a negative number is impossible. */
1460 retval = operandFromValue (valRecastLitVal (type, valShift (OP_VALUE (left), OP_VALUE (right), 0, true)), false);
1461 break;
1462 case EQ_OP:
1463 if (IS_FLOAT (let) || IS_FLOAT (ret))
1465 retval = operandFromLit (operandLitValue (left) == operandLitValue (right));
1467 else if (IS_FIXED16X16 (let) || IS_FIXED16X16 (ret))
1469 retval = operandFromLit (operandLitValue (left) == operandLitValue (right));
1471 else if (IS_PTR (operandType (left)) || IS_PTR (operandType (right)))
1473 retval = operandFromLit (operandLitValue (left) == operandLitValue (right));
1475 else
1477 /* this op doesn't care about signedness */
1478 TYPE_TARGET_ULONG l, r;
1480 l = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left));
1481 r = (TYPE_TARGET_ULONG) double2ul (operandLitValue (right));
1482 /* In order to correctly compare 'signed int' and 'unsigned int' it's
1483 necessary to strip them to 16 bit.
1484 Literals are reduced to their cheapest type, therefore left and
1485 right might have different types. It's necessary to find a
1486 common type: int (used for char too) or long */
1487 if (!IS_LONG (let) && !IS_LONG (ret))
1489 r = (TYPE_TARGET_UINT) r;
1490 l = (TYPE_TARGET_UINT) l;
1492 retval = operandFromLit (l == r);
1494 break;
1495 case '<':
1496 retval = operandFromLit (operandLitValue (left) < operandLitValue (right));
1497 break;
1498 case LE_OP:
1499 retval = operandFromLit (operandLitValue (left) <= operandLitValue (right));
1500 break;
1501 case NE_OP:
1502 retval = operandFromLit (operandLitValue (left) != operandLitValue (right));
1503 break;
1504 case '>':
1505 retval = operandFromLit (operandLitValue (left) > operandLitValue (right));
1506 break;
1507 case GE_OP:
1508 retval = operandFromLit (operandLitValue (left) >= operandLitValue (right));
1509 break;
1510 case BITWISEAND:
1511 retval = operandFromValue (valCastLiteral (type,
1512 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) &
1513 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)),
1514 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) &
1515 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))), false);
1516 break;
1517 case '|':
1518 retval = operandFromValue (valCastLiteral (type,
1519 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) |
1520 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)),
1521 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) |
1522 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))), false);
1523 break;
1524 case '^':
1525 retval = operandFromValue (valCastLiteral (type,
1526 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) ^
1527 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)),
1528 (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) ^
1529 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))), false);
1530 break;
1531 case AND_OP:
1532 retval = operandFromLit (operandLitValue (left) && operandLitValue (right));
1533 break;
1534 case OR_OP:
1535 retval = operandFromLit (operandLitValue (left) || operandLitValue (right));
1536 break;
1537 case ROT:
1539 TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left));
1540 unsigned s = operandLitValue (right) >= 0 ? operandLitValue (right) : bitsForType (operandType (left)) - operandLitValue (right);
1541 retval = operandFromLit ((i << s) | (i >> (bitsForType (operandType (left)) - s)));
1543 break;
1544 case GETABIT:
1545 retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) >>
1546 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))) & 1);
1547 break;
1548 case GETBYTE:
1549 retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) >>
1550 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) & 0xFF));
1551 break;
1552 case GETWORD:
1553 retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) >>
1554 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) & 0xFFFF));
1555 break;
1557 case UNARYMINUS:
1558 retval = operandFromValue (valCastLiteral (type, -1 * operandLitValue (left), (-1ll) * operandLitValueUll (left)), false);
1559 break;
1561 case '~':
1562 retval = operandFromValue (valCastLiteral (type, ~((TYPE_TARGET_ULONG) double2ul (operandLitValue (left))), ~((TYPE_TARGET_ULONGLONG) operandLitValueUll (left))), false);
1563 break;
1565 case '!':
1566 retval = operandFromLit (!operandLitValue (left));
1567 break;
1569 case ADDRESS_OF:
1570 retval = operandFromValue (valCastLiteral (type, operandLitValue (left), (TYPE_TARGET_ULONGLONG) operandLitValueUll (left)), false);
1571 break;
1573 default:
1574 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, " operandOperation invalid operator ");
1575 assert (0);
1578 return retval;
1581 /*-----------------------------------------------------------------*/
1582 /* isOperandEqual - compares two operand & return 1 if they are = */
1583 /*-----------------------------------------------------------------*/
1585 isOperandEqual (const operand * left, const operand * right)
1587 /* if the pointers are equal then they are equal */
1588 if (left == right)
1589 return 1;
1591 /* if either of them is null then false */
1592 if (!left || !right)
1593 return 0;
1595 if (left->type != right->type)
1596 return 0;
1598 if (IS_SYMOP (left) && IS_SYMOP (right))
1599 return left->key == right->key;
1601 /* if types are the same */
1602 switch (left->type)
1604 case SYMBOL:
1605 return isSymbolEqual (left->svt.symOperand, right->svt.symOperand);
1606 case VALUE:
1607 return (compareType (left->svt.valOperand->type, right->svt.valOperand->type, false) &&
1608 (!IS_FLOAT (getSpec (left->svt.valOperand->type)) ?
1609 (operandLitValueUll (left) == operandLitValueUll (right)) :
1610 (operandLitValue (left) == operandLitValue (right))));
1611 case TYPE:
1612 if (compareType (left->svt.typeOperand, right->svt.typeOperand, false) == 1)
1613 return 1;
1616 return 0;
1619 /*-------------------------------------------------------------------*/
1620 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1621 /*-------------------------------------------------------------------*/
1623 isiCodeEqual (iCode * left, iCode * right)
1625 /* if the same pointer */
1626 if (left == right)
1627 return 1;
1629 /* if either of them null */
1630 if (!left || !right)
1631 return 0;
1633 /* if operand are the same */
1634 if (left->op == right->op)
1636 /* compare all the elements depending on type */
1637 if (left->op != IFX)
1639 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1640 return 0;
1641 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1642 return 0;
1644 else
1646 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1647 return 0;
1648 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1649 return 0;
1650 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1651 return 0;
1654 return 1;
1656 return 0;
1659 /*-----------------------------------------------------------------*/
1660 /* newiTempFromOp - create a temp Operand with same attributes */
1661 /*-----------------------------------------------------------------*/
1662 operand *
1663 newiTempFromOp (operand * op)
1665 operand *nop;
1667 if (!op)
1668 return NULL;
1670 if (!IS_ITEMP (op))
1671 return op;
1673 nop = newiTempOperand (operandType (op), TRUE);
1674 nop->isaddr = op->isaddr;
1675 nop->isvolatile = op->isvolatile;
1676 nop->isGlobal = op->isGlobal;
1677 nop->isLiteral = op->isLiteral;
1678 nop->usesDefs = op->usesDefs;
1679 nop->isParm = op->isParm;
1680 return nop;
1683 /*-----------------------------------------------------------------*/
1684 /* operand from operand - creates an operand holder for the type */
1685 /*-----------------------------------------------------------------*/
1686 operand *
1687 operandFromOperand (operand * op)
1689 operand *nop;
1691 if (!op)
1692 return NULL;
1693 nop = newOperand ();
1694 nop->type = op->type;
1695 nop->isaddr = op->isaddr;
1696 nop->key = op->key;
1697 nop->isvolatile = op->isvolatile;
1698 nop->isGlobal = op->isGlobal;
1699 nop->isLiteral = op->isLiteral;
1700 nop->usesDefs = op->usesDefs;
1701 nop->isParm = op->isParm;
1702 nop->isConstElimnated = op->isConstElimnated;
1704 switch (nop->type)
1706 case SYMBOL:
1707 nop->svt.symOperand = op->svt.symOperand;
1708 break;
1709 case VALUE:
1710 nop->svt.valOperand = op->svt.valOperand;
1711 break;
1712 case TYPE:
1713 nop->svt.typeOperand = op->svt.typeOperand;
1714 break;
1717 return nop;
1720 /*-----------------------------------------------------------------*/
1721 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1722 /*-----------------------------------------------------------------*/
1723 operand *
1724 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1726 operand *nop = operandFromOperand (op);
1728 if (nop->type == SYMBOL)
1730 OP_DEFS (nop) = bitVectCopy (defs);
1731 OP_USES (nop) = bitVectCopy (uses);
1734 return nop;
1737 /*-----------------------------------------------------------------*/
1738 /* operandFromSymbol - creates an operand from a symbol */
1739 /*-----------------------------------------------------------------*/
1740 operand *
1741 operandFromSymbol (symbol *sym, bool convert_sym_to_ptr)
1743 operand *op;
1744 iCode *ic;
1745 int ok = 1;
1746 /* if the symbol's type is a literal */
1747 /* then it is an enumerator type */
1748 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1749 return operandFromValue (valFromType (sym->etype), convert_sym_to_ptr);
1751 if (!sym->key)
1752 sym->key = ++operandKey;
1754 /* if this an implicit variable, means struct/union */
1755 /* member so just return it */
1756 if (sym->implicit || IS_FUNC (sym->type))
1758 op = newOperand ();
1759 op->type = SYMBOL;
1760 op->svt.symOperand = sym;
1761 op->key = sym->key;
1762 op->isvolatile = isOperandVolatile (op, TRUE);
1763 op->isGlobal = isOperandGlobal (op);
1764 return op;
1767 /* under the following conditions create a
1768 register equivalent for a local symbol */
1769 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1770 (IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE && (!(options.model == MODEL_FLAT24))) && options.stackAuto == 0)
1772 ok = 0;
1775 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1776 !IS_FUNC (sym->type) && /* not a function */
1777 !sym->_isparm && /* not a parameter */
1778 IS_AUTO (sym) && /* is a local auto variable */
1779 !sym->addrtaken && /* whose address has not been taken */
1780 !sym->reqv && /* does not already have a reg equivalence */
1781 !IS_VOLATILE (sym->type) && /* not declared as volatile */
1782 !sym->islbl && /* not a label */
1783 !((TARGET_HC08_LIKE || TARGET_MOS6502_LIKE) && (getSize (sym->type) > 2)) && /* will fit in regs */
1784 ok /* farspace check */
1787 /* we will use it after all optimizations
1788 and before liveRange calculation */
1789 sym->reqv = newiTempOperand (sym->type, 0);
1790 sym->reqv->key = sym->key;
1791 OP_SYMBOL (sym->reqv)->prereqv = sym;
1792 OP_SYMBOL (sym->reqv)->key = sym->key;
1793 OP_SYMBOL (sym->reqv)->isreqv = 1;
1794 OP_SYMBOL (sym->reqv)->islocal = 1;
1795 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1796 SPIL_LOC (sym->reqv) = sym;
1799 if (!IS_AGGREGATE (sym->type) || !convert_sym_to_ptr && IS_STRUCT (sym->type))
1801 op = newOperand ();
1802 op->type = SYMBOL;
1803 op->svt.symOperand = sym;
1804 op->isaddr = 1;
1805 op->key = sym->key;
1806 op->isvolatile = isOperandVolatile (op, TRUE);
1807 op->isGlobal = isOperandGlobal (op);
1808 op->isPtr = IS_PTR (operandType (op));
1809 op->isParm = sym->_isparm;
1810 return op;
1813 /* create :- */
1814 /* itemp = &[_symbol] */
1816 ic = newiCode (ADDRESS_OF, newOperand (), operandFromLit (0));
1817 IC_LEFT (ic)->type = SYMBOL;
1818 IC_LEFT (ic)->svt.symOperand = sym;
1819 IC_LEFT (ic)->key = sym->key;
1820 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1821 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1822 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1824 /* create result */
1825 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1826 if (IS_ARRAY (sym->type))
1828 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1830 else
1832 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1835 ADDTOCHAIN (ic);
1837 return IC_RESULT (ic);
1840 /*-----------------------------------------------------------------*/
1841 /* operandFromValue - creates an operand from value */
1842 /*-----------------------------------------------------------------*/
1843 operand *
1844 operandFromValue (value *val, bool convert_sym_to_ptr)
1846 operand *op;
1848 /* if this is a symbol then do the symbol thing */
1849 if (val->sym)
1850 return operandFromSymbol (val->sym, convert_sym_to_ptr);
1852 /* this is not a symbol */
1853 op = newOperand ();
1854 op->type = VALUE;
1855 op->svt.valOperand = val;
1856 op->isLiteral = isOperandLiteral (op);
1857 return op;
1860 /*-----------------------------------------------------------------*/
1861 /* operandFromLink - operand from typeChain */
1862 /*-----------------------------------------------------------------*/
1863 operand *
1864 operandFromLink (sym_link * type)
1866 operand *op;
1868 /* operand from sym_link */
1869 if (!type)
1870 return NULL;
1872 op = newOperand ();
1873 op->type = TYPE;
1874 op->svt.typeOperand = copyLinkChain (type);
1875 return op;
1878 /*-----------------------------------------------------------------*/
1879 /* operandFromLit - makes an operand from a literal value */
1880 /*-----------------------------------------------------------------*/
1881 operand *
1882 operandFromLit (double i)
1884 return operandFromValue (valueFromLit (i), false);
1887 /*-----------------------------------------------------------------*/
1888 /* operandFromAst - creates an operand from an ast */
1889 /*-----------------------------------------------------------------*/
1890 static operand *
1891 operandFromAst (ast * tree, int lvl, bool convert_sym_to_ptr)
1893 if (!tree)
1894 return NULL;
1896 /* depending on type do */
1897 switch (tree->type)
1899 case EX_OP:
1900 return ast2iCode (tree, lvl + 1);
1901 break;
1903 case EX_VALUE:
1904 return operandFromValue (tree->opval.val, convert_sym_to_ptr);
1905 break;
1907 case EX_LINK:
1908 return operandFromLink (tree->opval.lnk);
1909 break;
1911 default:
1912 assert (0);
1915 /* Just to keep the compiler happy */
1916 return (operand *) 0;
1919 /*-----------------------------------------------------------------*/
1920 /* setOperandType - sets the operand's type to the given type */
1921 /*-----------------------------------------------------------------*/
1922 void
1923 setOperandType (operand * op, sym_link * type)
1925 /* depending on the type of operand */
1926 switch (op->type)
1928 case VALUE:
1929 op->svt.valOperand->etype = getSpec (op->svt.valOperand->type = copyLinkChain (type));
1930 return;
1932 case SYMBOL:
1933 if (op->svt.symOperand->isitmp)
1935 op->svt.symOperand->etype = getSpec (op->svt.symOperand->type = copyLinkChain (type));
1936 if (IS_SPEC (op->svt.symOperand->type))
1938 SPEC_SCLS (op->svt.symOperand->etype) = S_REGISTER;
1939 SPEC_OCLS (op->svt.symOperand->etype) = reg;
1942 else
1943 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "attempt to modify type of source");
1944 return;
1946 case TYPE:
1947 op->svt.typeOperand = copyLinkChain (type);
1948 return;
1952 /*-----------------------------------------------------------------*/
1953 /* Get size in byte of ptr need to access an array */
1954 /*-----------------------------------------------------------------*/
1955 static unsigned int
1956 getArraySizePtr (operand * op)
1958 sym_link *ltype = operandType (op);
1960 if (IS_PTR (ltype))
1962 int size = getSize (ltype);
1963 return ((IS_GENPTR (ltype) && GPTRSIZE > FARPTRSIZE) ? (size - 1) : size);
1966 if (IS_ARRAY (ltype))
1968 sym_link *letype = getSpec (ltype);
1969 switch (PTR_TYPE (SPEC_OCLS (letype)))
1971 case IPOINTER:
1972 case PPOINTER:
1973 case POINTER:
1974 return (NEARPTRSIZE);
1975 case EEPPOINTER:
1976 case FPOINTER:
1977 case CPOINTER:
1978 case FUNCTION:
1979 return (FARPTRSIZE);
1980 case GPOINTER:
1981 if (GPTRSIZE > FARPTRSIZE)
1982 return (GPTRSIZE - 1);
1983 else
1984 return (FARPTRSIZE);
1986 default:
1987 return (FARPTRSIZE);
1990 return (FARPTRSIZE);
1993 /*-----------------------------------------------------------------*/
1994 /* perform "usual unary conversions" */
1995 /*-----------------------------------------------------------------*/
1996 #if 0
1997 static operand *
1998 usualUnaryConversions (operand * op)
2000 if (IS_INTEGRAL (operandType (op)))
2002 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
2004 /* Widen to int. */
2005 return geniCodeCast (INTTYPE, op, TRUE);
2008 return op;
2010 #endif
2012 /*-----------------------------------------------------------------*/
2013 /* perform "usual binary conversions" */
2014 /*-----------------------------------------------------------------*/
2016 static sym_link *
2017 usualBinaryConversions (operand ** op1, operand ** op2, RESULT_TYPE resultType, int op)
2019 sym_link *ctype;
2020 sym_link *rtype = operandType (*op2);
2021 sym_link *ltype = operandType (*op1);
2023 ctype = computeType (ltype, rtype, resultType, op);
2025 switch (op)
2027 case '*':
2028 case '/':
2029 case '%':
2030 if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
2032 /* one byte operations: keep signedness for code generator */
2033 return ctype;
2035 break;
2036 case LEFT_OP:
2037 case RIGHT_OP:
2038 case ROT:
2039 *op1 = geniCodeCast (ctype, *op1, true);
2040 return ctype;
2041 default:
2042 break;
2045 *op1 = geniCodeCast (ctype, *op1, TRUE);
2046 *op2 = geniCodeCast (ctype, *op2, TRUE);
2048 return ctype;
2051 /*-----------------------------------------------------------------*/
2052 /* geniCodeValueAtAddress - generate intermediate code for value */
2053 /* at address */
2054 /*-----------------------------------------------------------------*/
2055 operand *
2056 geniCodeRValue (operand * op, bool force)
2058 iCode *ic;
2059 sym_link *type = operandType (op);
2060 sym_link *etype = getSpec (type);
2062 /* if this is an array & already */
2063 /* a resolved address then return this */
2064 if ((IS_ARRAY (type) && !IS_FUNCPTR (type->next)) || IS_STRUCT (type) || (IS_PTR (type) && !force && !op->isaddr))
2065 return operandFromOperand (op);
2067 /* if this is not an address then must be */
2068 /* rvalue already so return this one */
2069 if (!op->isaddr)
2070 return op;
2072 /* if this is not a temp symbol then */
2073 if (!IS_ITEMP (op) && !force && !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE))
2075 op = operandFromOperand (op);
2076 op->isaddr = 0;
2077 return op;
2080 if (IS_SPEC (type) &&
2081 IS_TRUE_SYMOP (op) && (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE) || (options.model == MODEL_FLAT24)))
2083 op = operandFromOperand (op);
2084 op->isaddr = 0;
2085 return op;
2088 ic = newiCode (GET_VALUE_AT_ADDRESS, op, operandFromLit (0));
2089 if ((IS_PTR (type) && op->isaddr && force) || IS_ARRAY (type))
2090 type = type->next;
2092 type = copyLinkChain (type);
2094 IC_RESULT (ic) = newiTempOperand (type, 1);
2095 IC_RESULT (ic)->isaddr = 0;
2097 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
2099 ADDTOCHAIN (ic);
2101 return IC_RESULT (ic);
2104 /*-----------------------------------------------------------------*/
2105 /* checkPtrQualifiers - check for lost pointer qualifiers */
2106 /*-----------------------------------------------------------------*/
2107 static void
2108 checkPtrQualifiers (sym_link * ltype, sym_link * rtype, int warn_const)
2110 if (IS_PTR (ltype) && IS_PTR (rtype) && !IS_FUNCPTR (ltype) && warn_const)
2112 if (!IS_CONSTANT (ltype->next) && IS_CONSTANT (rtype->next))
2113 werror (W_TARGET_LOST_QUALIFIER, "const");
2114 #if 0
2115 // disabled because SDCC will make all union fields volatile
2116 // but your ptr to it need not be
2117 if (!IS_VOLATILE (ltype->next) && IS_VOLATILE (rtype->next))
2118 werror (W_TARGET_LOST_QUALIFIER, "volatile");
2119 #endif
2120 if (!IS_RESTRICT (ltype->next) && IS_RESTRICT (rtype->next))
2121 werror (W_TARGET_LOST_QUALIFIER, "restrict");
2125 /*-----------------------------------------------------------------*/
2126 /* geniCodeCast - changes the value from one type to another */
2127 /*-----------------------------------------------------------------*/
2128 static operand *
2129 geniCodeCast (sym_link *type, operand *op, bool implicit)
2131 iCode *ic;
2132 sym_link *optype;
2133 sym_link *opetype = getSpec (optype = operandType (op));
2134 sym_link *restype;
2136 /* one of them has size zero then error */
2137 if (IS_VOID (optype))
2139 werror (E_CAST_ZERO);
2140 return op;
2143 if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
2145 geniCodeArray2Ptr (op);
2148 /* if the operand is already the desired type then do nothing */
2149 if (compareType (type, optype, false) == 1)
2151 if (IS_PTR (type) && IS_CONSTANT (opetype) && !IS_CONSTANT (getSpec(type)))
2152 op->isConstElimnated = 1;
2153 return op;
2156 /* if this is a literal then just change the type & return */
2157 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
2159 return operandFromValue (valCastLiteral (type, operandLitValue (op), operandLitValueUll (op)), false);
2162 checkPtrCast (type, optype, implicit, IS_OP_LITERAL (op) && !operandLitValue (op));
2164 ic = newiCode (CAST, operandFromLink (type), geniCodeRValue (op, FALSE));
2165 IC_RESULT (ic) = newiTempOperand (type, 0);
2167 restype = getSpec (operandType (IC_RESULT (ic)));
2168 /* Convert cast to _Bool bitfield members to casts to _Bool. */
2169 if (SPEC_NOUN (restype) == V_BBITFIELD)
2170 SPEC_NOUN (restype) = V_BOOL;
2172 ADDTOCHAIN (ic);
2173 return IC_RESULT (ic);
2176 /*-----------------------------------------------------------------*/
2177 /* geniCodeLabel - will create a Label */
2178 /*-----------------------------------------------------------------*/
2179 void
2180 geniCodeLabel (symbol * label)
2182 iCode *ic;
2184 ic = newiCodeLabelGoto (LABEL, label);
2185 ADDTOCHAIN (ic);
2188 /*-----------------------------------------------------------------*/
2189 /* geniCodeGoto - will create a Goto */
2190 /*-----------------------------------------------------------------*/
2191 void
2192 geniCodeGoto (symbol * label)
2194 iCode *ic;
2196 ic = newiCodeLabelGoto (GOTO, label);
2197 ADDTOCHAIN (ic);
2200 /*-----------------------------------------------------------------*/
2201 /* geniCodeMultiply - gen intermediate code for multiplication */
2202 /*-----------------------------------------------------------------*/
2203 static operand *
2204 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2206 iCode *ic;
2207 int p2 = 0;
2208 sym_link *resType;
2209 LRTYPE;
2211 /* if they are both literal then we know the result */
2212 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2213 return operandFromValue (valMult (OP_VALUE (left), OP_VALUE (right), true), false);
2215 if (IS_LITERAL (retype))
2217 p2 = powof2 ((TYPE_TARGET_ULONG) ulFromVal (OP_VALUE (right)));
2220 resType = usualBinaryConversions (&left, &right, resultType, '*');
2221 rtype = operandType (right);
2222 retype = getSpec (rtype);
2223 ltype = operandType (left);
2224 letype = getSpec (ltype);
2226 /* if the right is a literal & power of 2 */
2227 /* then make it a left shift */
2228 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2229 efficient in most cases than 2 bytes result = 2 bytes << literal
2230 if port has 1 byte muldiv */
2231 if ((p2 > 0) && !IS_FLOAT (letype) && !IS_FIXED (letype) &&
2232 !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)) && !(TARGET_Z80_LIKE || TARGET_MOS6502_LIKE || TARGET_IS_F8 || TARGET_IS_STM8 && p2 == 1) /* Mimic old behaviour that tested port->muldiv, which was zero for stm8 and z80-like only. Someone should look into what really makes sense here. */) &&
2233 !TARGET_PIC_LIKE) /* don't shift for pic */
2235 if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2237 /* LEFT_OP need same size for left and result, */
2238 left = geniCodeCast (resType, left, TRUE);
2239 ltype = operandType (left);
2241 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2243 else
2245 /* if the size left or right > 1 then support routine */
2246 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2248 if (IS_LITERAL (retype))
2249 ic = newiCode ('*', right, left); /* multiplication by support routine with one literal */
2250 else
2251 ic = newiCode ('*', left, right); /* multiplication by support routine */
2252 ic->supportRtn = 1;
2254 else
2256 ic = newiCode ('*', left, right); /* normal multiplication */
2259 IC_RESULT (ic) = newiTempOperand (resType, 1);
2261 ADDTOCHAIN (ic);
2262 return IC_RESULT (ic);
2265 static operand *
2266 geniCodeAdd (operand *left, operand *right, RESULT_TYPE resultType, int lvl);
2267 static operand *
2268 geniCodeLogic (operand *left, operand *right, int op, ast *tree);
2269 operand *
2270 geniCodeRightShift (operand *left, operand *right);
2272 /*-----------------------------------------------------------------*/
2273 /* geniCodeDivision - gen intermediate code for division */
2274 /*-----------------------------------------------------------------*/
2275 static operand *
2276 geniCodeDivision (operand *left, operand *right, RESULT_TYPE resultType, bool ptrdiffdiv)
2278 iCode *ic;
2279 int p2 = 0;
2280 sym_link *resType = usualBinaryConversions (&left, &right, resultType, '/');
2281 sym_link *rtype = operandType (right);
2282 sym_link *retype = getSpec (rtype);
2283 sym_link *ltype = operandType (left);
2284 sym_link *letype = getSpec (ltype);
2286 /* if the right is a literal & power of 2 and left is unsigned then
2287 make it a right shift.
2288 For pointer division, there can be no remainder, so we can make
2289 it a right shift, too. */
2291 if (IS_LITERAL (retype) &&
2292 (!IS_FLOAT (letype) && !IS_FIXED (letype) && IS_UNSIGNED (letype) || ptrdiffdiv) &&
2293 ((p2 = powof2 ((TYPE_TARGET_ULONGLONG) ullFromVal (OP_VALUE (right)))) > 0))
2295 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2297 /* if the right is a literal & power of 2
2298 and left is signed then make it a conditional addition
2299 followed by right shift */
2300 else if (IS_LITERAL (retype) &&
2301 !IS_FLOAT (letype) &&
2302 !IS_FIXED (letype) && !IS_UNSIGNED (letype) &&
2303 floatFromVal (OP_VALUE (right)) >= 0 &&
2304 ((p2 = powof2 ((TYPE_TARGET_ULONGLONG) ullFromVal (OP_VALUE (right)))) > 0) &&
2305 (TARGET_Z80_LIKE || TARGET_HC08_LIKE || TARGET_MOS6502_LIKE))
2307 operand *tmp;
2308 symbol *label = newiTempLabel (NULL);
2310 tmp = newiTempOperand (ltype, 0);
2311 geniCodeAssign (tmp, left, 0, 0);
2313 ic = newiCodeCondition (geniCodeLogic (tmp, operandFromLit (0), '<', 0), 0, label);
2314 ADDTOCHAIN (ic);
2316 geniCodeAssign (tmp, geniCodeAdd (tmp, operandFromLit ((1 << p2) - 1), 0, 0), 0, 0);
2317 geniCodeLabel (label);
2318 return (geniCodeCast (resType, geniCodeRightShift (tmp, operandFromLit (p2)), TRUE));
2321 else
2323 ic = newiCode ('/', left, right); /* normal division */
2324 /* if the size left or right > 1 then support routine */
2325 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2326 ic->supportRtn = 1;
2328 IC_RESULT (ic) = newiTempOperand (resType, 0);
2330 ADDTOCHAIN (ic);
2331 return IC_RESULT (ic);
2334 /*-----------------------------------------------------------------*/
2335 /* geniCodeModulus - gen intermediate code for modulus */
2336 /*-----------------------------------------------------------------*/
2337 static operand *
2338 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2340 iCode *ic;
2341 sym_link *resType;
2342 LRTYPE;
2344 /* if they are both literal then we know the result */
2345 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2346 return operandFromValue (valMod (OP_VALUE (left), OP_VALUE (right), true), false);
2348 resType = usualBinaryConversions (&left, &right, resultType, '%');
2350 /* now they are the same size */
2351 ic = newiCode ('%', left, right);
2353 /* if the size left or right > 1 then support routine */
2354 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2355 ic->supportRtn = 1;
2356 IC_RESULT (ic) = newiTempOperand (resType, 0);
2358 ADDTOCHAIN (ic);
2359 return IC_RESULT (ic);
2362 /*-----------------------------------------------------------------*/
2363 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2364 /*-----------------------------------------------------------------*/
2365 operand *
2366 geniCodePtrPtrSubtract (operand * left, operand * right)
2368 iCode *ic;
2369 operand *result;
2370 LRTYPE;
2372 /* if they are both literals then */
2373 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2375 result = operandFromValue (valMinus (OP_VALUE (left), OP_VALUE (right), true), true);
2376 goto subtractExit;
2379 ic = newiCode ('-', left, right);
2381 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2382 ADDTOCHAIN (ic);
2384 subtractExit:
2385 if (IS_VOID (ltype->next) || IS_VOID (rtype->next))
2387 return result;
2390 return geniCodeDivision (result, operandFromLit (getSize (ltype->next)), FALSE, true);
2393 /*-----------------------------------------------------------------*/
2394 /* geniCodeSubtract - generates code for subtraction */
2395 /*-----------------------------------------------------------------*/
2396 static operand *
2397 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2399 iCode *ic;
2400 int isarray = 0;
2401 sym_link *resType;
2402 LRTYPE;
2404 /* if they are both pointers then */
2405 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) && (IS_PTR (rtype) || IS_ARRAY (rtype)))
2406 return geniCodePtrPtrSubtract (left, right);
2408 /* if they are both literal then we know the result */
2409 if (IS_LITERAL (letype) && IS_LITERAL (retype) && left->isLiteral && right->isLiteral)
2410 return operandFromValue (valMinus (OP_VALUE (left), OP_VALUE (right), true), false);
2412 /* if left is an array or pointer */
2413 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2415 isarray = left->isaddr;
2416 right = geniCodeMultiply (right,
2417 operandFromLit (getSize (ltype->next)),
2418 (getArraySizePtr (left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR);
2419 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2421 else
2422 { /* make them the same size */
2423 resType = usualBinaryConversions (&left, &right, resultType, '-');
2426 ic = newiCode ('-', left, right);
2428 IC_RESULT (ic) = newiTempOperand (resType, 1);
2429 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2431 /* if left or right is a float */
2432 if (IS_FLOAT (ltype) || IS_FLOAT (rtype) || IS_FIXED (ltype) || IS_FIXED (rtype))
2433 ic->supportRtn = 1;
2435 ADDTOCHAIN (ic);
2436 return IC_RESULT (ic);
2439 /*-----------------------------------------------------------------*/
2440 /* geniCodeAdd - generates iCode for addition */
2441 /*-----------------------------------------------------------------*/
2442 static operand *
2443 geniCodeAdd (operand *left, operand *right, RESULT_TYPE resultType, int lvl)
2445 iCode *ic;
2446 sym_link *resType;
2447 unsigned int nBytes;
2448 operand *size;
2449 int isarray = 0;
2450 bool indexUnsigned;
2451 LRTYPE;
2453 /* if the right side is LITERAL zero */
2454 /* return the left side */
2455 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2456 return left;
2458 /* if left is literal zero return right */
2459 if (!IS_PTR (ltype) && IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2460 return right;
2462 /* if left is a pointer then size */
2463 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2465 unsigned int ptrSize;
2466 isarray = left->isaddr;
2467 nBytes = getSize (ltype->next);
2468 ptrSize = getArraySizePtr (left); // works for both arrays and pointers
2470 if (nBytes == 0 && !IS_VOID (ltype->next))
2471 werror (E_UNKNOWN_SIZE, IS_SYMOP (left) ? OP_SYMBOL (left)->name : "<no name>");
2472 // there is no need to multiply with 1
2473 if (nBytes != 1)
2475 size = operandFromLit (nBytes);
2476 SPEC_USIGN (getSpec (operandType (size))) = 1;
2477 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2478 if (!indexUnsigned && ptrSize > INTSIZE)
2480 SPEC_LONG (getSpec (operandType (size))) = 1;
2481 SPEC_CVAL (getSpec (operandType (size))).v_ulong = nBytes;
2483 right = geniCodeMultiply (right, size, (ptrSize >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR);
2484 /* Even if right is a 'unsigned char',
2485 the result will be a 'signed int' due to the promotion rules.
2486 It doesn't make sense when accessing arrays, so let's fix it here: */
2487 if (indexUnsigned)
2488 SPEC_USIGN (getSpec (operandType (right))) = 1;
2491 if (ptrSize > getSize (rtype) && !IS_UNSIGNED (retype))
2493 sym_link *type = 0;
2495 switch(ptrSize)
2497 case 2:
2498 type = newIntLink();
2499 break;
2500 case 3:
2501 case 4:
2502 type = newLongLink();
2503 break;
2504 default:
2505 wassert(0);
2507 right = geniCodeCast (type, right, TRUE);
2510 resType = copyLinkChain (ltype);
2512 else
2513 { // make them the same size
2514 resType = usualBinaryConversions (&left, &right, resultType, '+');
2517 /* if they are both literals then we know */
2518 if (IS_LITERAL (letype) && IS_LITERAL (retype) && left->isLiteral && right->isLiteral)
2520 value *scaledRight = valFromType (rtype);
2521 if (IS_PTR (ltype))
2522 scaledRight = valMult (scaledRight, valueFromLit (getSize (ltype->next)), true);
2523 return operandFromValue (valPlus (valFromType (ltype), scaledRight, true), false);
2526 ic = newiCode ('+', left, right);
2528 IC_RESULT (ic) = newiTempOperand (resType, 1);
2529 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2531 /* if left or right is a float then support routine */
2532 if (IS_FLOAT (ltype) || IS_FLOAT (rtype) || IS_FIXED (ltype) || IS_FIXED (rtype))
2533 ic->supportRtn = 1;
2535 ADDTOCHAIN (ic);
2537 return IC_RESULT (ic);
2540 /*-----------------------------------------------------------------*/
2541 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2542 /*-----------------------------------------------------------------*/
2543 sym_link *
2544 aggrToPtr (sym_link * type, bool force)
2546 sym_link *etype;
2547 sym_link *ptype;
2549 if (IS_PTR (type) && !force)
2550 return type;
2552 etype = getSpec (type);
2553 ptype = newLink (DECLARATOR);
2555 ptype->next = type;
2557 /* set the pointer depending on the storage class */
2558 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2559 return ptype;
2562 /*------------------------------------------------------------------*/
2563 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2564 /*------------------------------------------------------------------*/
2566 aggrToPtrDclType (sym_link * type, bool force)
2568 if (IS_PTR (type) && !force)
2569 return DCL_TYPE (type);
2571 /* return the pointer depending on the storage class */
2572 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2575 /*-----------------------------------------------------------------*/
2576 /* geniCodeArray2Ptr - array to pointer */
2577 /*-----------------------------------------------------------------*/
2578 static operand *
2579 geniCodeArray2Ptr (operand * op)
2581 sym_link *optype = operandType (op);
2582 sym_link *opetype = getSpec (optype);
2584 /* set the pointer depending on the storage class */
2585 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2586 /* now remove the storage class from this itemp */
2587 SPEC_SCLS (opetype) = S_FIXED;
2588 SPEC_OCLS (opetype) = NULL;
2590 op->isaddr = 0;
2591 return op;
2595 /*-----------------------------------------------------------------*/
2596 /* geniCodeArray - array access */
2597 /*-----------------------------------------------------------------*/
2598 static operand *
2599 geniCodeArray (operand * left, operand * right, int lvl, bool noderef)
2601 iCode *ic;
2602 operand *size;
2603 sym_link *ltype = operandType (left);
2604 bool indexUnsigned;
2605 RESULT_TYPE resultType;
2607 resultType = (getArraySizePtr (left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
2608 if (DCL_ELEM (ltype))
2610 if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
2611 resultType = RESULT_TYPE_CHAR;
2614 if (IS_PTR (ltype))
2616 if (IS_PTR (ltype->next) && left->isaddr)
2618 left = geniCodeRValue (left, FALSE);
2621 if (noderef)
2622 return geniCodeAdd (left, right, resultType, lvl);
2624 return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl), lvl);
2626 size = operandFromLit (getSize (ltype->next));
2627 SPEC_USIGN (getSpec (operandType (size))) = 1;
2628 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2629 right = geniCodeMultiply (right, size, resultType);
2630 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2631 It doesn't make sense when accessing arrays, so let's fix it here: */
2632 if (indexUnsigned)
2633 SPEC_USIGN (getSpec (operandType (right))) = 1;
2634 /* we can check for limits here */
2635 /* already done in SDCCast.c
2636 if (isOperandLiteral (right) &&
2637 IS_ARRAY (ltype) &&
2638 DCL_ELEM (ltype) &&
2639 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2641 werror (W_IDX_OUT_OF_BOUNDS,
2642 (int) operandLitValue (right) / getSize (ltype->next),
2643 DCL_ELEM (ltype));
2647 ic = newiCode ('+', left, right);
2649 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) && !IS_AGGREGATE (ltype->next) && !IS_PTR (ltype->next)) ||
2650 (IS_ARRAY (ltype) && IS_FUNCPTR (ltype->next))) ? ltype : ltype->next, 0);
2652 if (!IS_AGGREGATE (ltype->next))
2654 IC_RESULT (ic)->isaddr = 1;
2655 IC_RESULT (ic)->aggr2ptr = 1;
2657 ADDTOCHAIN (ic);
2659 return IC_RESULT (ic);
2662 /*-----------------------------------------------------------------*/
2663 /* geniCodeStruct - generates intermediate code for structures */
2664 /*-----------------------------------------------------------------*/
2665 operand *
2666 geniCodeStruct (operand * left, operand * right, bool islval)
2668 iCode *ic;
2669 sym_link *type = operandType (left);
2670 sym_link *etype = getSpec (type);
2671 sym_link *rtype, *retype;
2672 symbol *element = getStructElement (SPEC_STRUCT (etype), OP_SYMBOL (right));
2674 wassert (IS_SYMOP (right));
2676 wassert (IS_STRUCT (type) || ((IS_PTR (type) || IS_ARRAY (type)) && IS_STRUCT (type->next)));
2678 /* add the offset */
2679 ic = newiCode ('+', left, operandFromLit (element->offset));
2681 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2683 /* preserve the storage & output class of the struct */
2684 /* as well as the volatile attribute */
2685 rtype = operandType (IC_RESULT (ic));
2686 retype = getSpec (rtype);
2687 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2688 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2690 if (IS_PTR (element->type))
2692 DCL_PTR_CONST (rtype) |= DCL_PTR_CONST (element->type);
2693 DCL_PTR_VOLATILE (rtype) |= DCL_PTR_VOLATILE (element->type);
2694 DCL_PTR_RESTRICT (rtype) |= DCL_PTR_RESTRICT (element->type);
2695 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2697 else
2699 SPEC_CONST (retype) |= SPEC_CONST (etype);
2700 /*Do not preserve volatile */
2701 SPEC_RESTRICT (retype) |= SPEC_RESTRICT (etype);
2704 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2706 ADDTOCHAIN (ic);
2707 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2710 /*-----------------------------------------------------------------*/
2711 /* geniCodePostInc - generate int code for Post increment */
2712 /*-----------------------------------------------------------------*/
2713 operand *
2714 geniCodePostInc (operand * op)
2716 iCode *ic;
2717 operand *rOp;
2718 sym_link *optype = operandType (op);
2719 operand *result;
2720 operand *rv = (IS_ITEMP (op) ? geniCodeRValue (op, (!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE) : op);
2721 sym_link *rvtype = operandType (rv);
2722 int size = 0;
2723 operand *srcOp = rv;
2725 /* if this is not an address we have trouble */
2726 if (!op->isaddr)
2728 werror (E_LVALUE_REQUIRED, "++");
2729 return op;
2732 rOp = newiTempOperand (rvtype, 0);
2733 OP_SYMBOL (rOp)->noSpilLoc = 1;
2735 if (IS_ITEMP (rv))
2736 OP_SYMBOL (rv)->noSpilLoc = 1;
2738 geniCodeAssign (rOp, rv, 0, 0);
2740 /* If rv is volatile, we can only read it once, and we've just */
2741 /* done that, so use the copy in rOp instead to avoid reading */
2742 /* it again. */
2743 if (isOperandVolatile (rv, FALSE))
2744 srcOp = rOp;
2746 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2747 if (size == 0)
2748 werror (W_SIZEOF_VOID);
2749 if (IS_FLOAT (rvtype))
2750 ic = newiCode ('+', srcOp, operandFromValue (constFloatVal ("1.0"), false));
2751 else if (IS_FIXED16X16 (rvtype))
2752 ic = newiCode ('+', srcOp, operandFromValue (constFixed16x16Val ("1.0"), false));
2753 else if (IS_BOOL (rvtype))
2754 ic = newiCode ('=', NULL, operandFromLit (1));
2755 else
2756 ic = newiCode ('+', srcOp, operandFromLit (size));
2758 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2759 ADDTOCHAIN (ic);
2761 geniCodeAssign (op, result, 0, 0);
2763 return rOp;
2767 /*-----------------------------------------------------------------*/
2768 /* geniCodePreInc - generate code for preIncrement */
2769 /*-----------------------------------------------------------------*/
2770 operand *
2771 geniCodePreInc (operand * op, bool lvalue)
2773 iCode *ic;
2774 sym_link *optype = operandType (op);
2775 operand *rop = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2776 sym_link *roptype = operandType (rop);
2777 operand *result;
2778 int size = 0;
2780 if (!op->isaddr)
2782 werror (E_LVALUE_REQUIRED, "++");
2783 return op;
2786 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2787 if (size == 0)
2788 werror (W_SIZEOF_VOID);
2789 if (IS_FLOAT (roptype))
2790 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0"), false));
2791 else if (IS_FIXED16X16 (roptype))
2792 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0"), false));
2793 else if (IS_BOOL (roptype))
2794 ic = newiCode ('=', NULL, operandFromLit (1));
2795 else
2796 ic = newiCode ('+', rop, operandFromLit (size));
2797 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2798 ADDTOCHAIN (ic);
2800 (void) geniCodeAssign (op, result, 0, 0);
2801 if (lvalue || (IS_TRUE_SYMOP (op) && !isOperandVolatile (op, FALSE)) || IS_BITVAR (optype))
2802 return op;
2803 else
2804 return result;
2807 /*-----------------------------------------------------------------*/
2808 /* geniCodePostDec - generates code for Post decrement */
2809 /*-----------------------------------------------------------------*/
2810 operand *
2811 geniCodePostDec (operand * op)
2813 iCode *ic;
2814 operand *rOp;
2815 sym_link *optype = operandType (op);
2816 operand *result;
2817 operand *rv = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2818 sym_link *rvtype = operandType (rv);
2819 int size = 0;
2820 operand *srcOp = rv;
2822 /* if this is not an address we have trouble */
2823 if (!op->isaddr)
2825 werror (E_LVALUE_REQUIRED, "--");
2826 return op;
2829 rOp = newiTempOperand (rvtype, 0);
2830 OP_SYMBOL (rOp)->noSpilLoc = 1;
2832 if (IS_ITEMP (rv))
2833 OP_SYMBOL (rv)->noSpilLoc = 1;
2835 geniCodeAssign (rOp, rv, 0, 0);
2837 /* If rv is volatile, we can only read it once, and we've just */
2838 /* done that, so use the copy in rOp instead to avoid reading */
2839 /* it again. */
2840 if (isOperandVolatile (rv, FALSE))
2841 srcOp = rOp;
2843 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2844 if (size == 0)
2845 werror (W_SIZEOF_VOID);
2846 if (IS_FLOAT (rvtype))
2847 ic = newiCode ('-', srcOp, operandFromValue (constFloatVal ("1.0"), false));
2848 else if (IS_FIXED16X16 (rvtype))
2849 ic = newiCode ('-', srcOp, operandFromValue (constFixed16x16Val ("1.0"), false));
2850 else if (IS_BOOL (rvtype))
2851 ic = newiCode ('!', srcOp, 0);
2852 else
2853 ic = newiCode ('-', srcOp, operandFromLit (size));
2855 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2856 ADDTOCHAIN (ic);
2858 geniCodeAssign (op, result, 0, 0);
2860 return rOp;
2864 /*-----------------------------------------------------------------*/
2865 /* geniCodePreDec - generate code for pre decrement */
2866 /*-----------------------------------------------------------------*/
2867 operand *
2868 geniCodePreDec (operand * op, bool lvalue)
2870 iCode *ic;
2871 sym_link *optype = operandType (op);
2872 operand *rop = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2873 sym_link *roptype = operandType (rop);
2874 operand *result;
2875 int size = 0;
2877 if (!op->isaddr)
2879 werror (E_LVALUE_REQUIRED, "--");
2880 return op;
2883 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2884 if (size == 0)
2885 werror (W_SIZEOF_VOID);
2886 if (IS_FLOAT (roptype))
2887 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0"), false));
2888 else if (IS_FIXED16X16 (roptype))
2889 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0"), false));
2890 else if (IS_BOOL (roptype))
2891 ic = newiCode ('!', rop, 0);
2892 else
2893 ic = newiCode ('-', rop, operandFromLit (size));
2894 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2895 ADDTOCHAIN (ic);
2897 (void) geniCodeAssign (op, result, 0, 0);
2898 if (lvalue || (IS_TRUE_SYMOP (op) && !isOperandVolatile (op, FALSE)) || IS_BITVAR (optype))
2899 return op;
2900 else
2901 return result;
2905 /*-----------------------------------------------------------------*/
2906 /* geniCodeBitwise - gen int code for bitWise operators */
2907 /*-----------------------------------------------------------------*/
2908 operand *
2909 geniCodeBitwise (operand * left, operand * right, int oper, sym_link * resType)
2911 iCode *ic;
2913 /* Signedness doesn't matter for bit ops, so omit */
2914 /* possible cast if that is the only difference */
2915 if (compareType (resType, operandType (left), false) != -2)
2916 left = geniCodeCast (resType, left, TRUE);
2917 if (compareType (resType, operandType (right), false) != -2)
2918 right = geniCodeCast (resType, right, TRUE);
2920 ic = newiCode (oper, left, right);
2921 IC_RESULT (ic) = newiTempOperand (resType, 0);
2923 ADDTOCHAIN (ic);
2924 return IC_RESULT (ic);
2927 /*-----------------------------------------------------------------*/
2928 /* geniCodeAddressOf - gens icode for '&' address of operator */
2929 /*-----------------------------------------------------------------*/
2930 operand *
2931 geniCodeAddressOf (operand * op)
2933 iCode *ic;
2934 sym_link *p;
2935 sym_link *optype = operandType (op);
2936 sym_link *opetype = getSpec (optype);
2938 if (IS_ITEMP (op) && IS_PTR (optype))
2940 op = operandFromOperand (op);
2941 op->isaddr = 0;
2942 return op;
2945 /* lvalue check already done in decorateType */
2946 /* this must be a lvalue */
2947 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2948 /* werror (E_LVALUE_REQUIRED,"&"); */
2949 /* return op; */
2950 /* } */
2952 p = newLink (DECLARATOR);
2954 /* set the pointer depending on the storage class */
2955 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2957 p->next = copyLinkChain (optype);
2959 /* if already a temp */
2960 if (IS_ITEMP (op))
2962 setOperandType (op, p);
2963 op->isaddr = 0;
2964 return op;
2967 /* otherwise make this of the type coming in */
2968 ic = newiCode (ADDRESS_OF, op, operandFromLit (0));
2969 IC_RESULT (ic) = newiTempOperand (p, 1);
2970 IC_RESULT (ic)->isaddr = 0;
2971 ADDTOCHAIN (ic);
2972 return IC_RESULT (ic);
2975 /*-----------------------------------------------------------------*/
2976 /* setOClass - sets the output class depending on the pointer type */
2977 /*-----------------------------------------------------------------*/
2978 void
2979 setOClass (sym_link * ptr, sym_link * spec)
2981 switch (DCL_TYPE (ptr))
2983 case POINTER:
2984 SPEC_OCLS (spec) = data;
2985 break;
2987 case GPOINTER:
2988 SPEC_OCLS (spec) = generic;
2989 break;
2991 case FPOINTER:
2992 SPEC_OCLS (spec) = xdata;
2993 break;
2995 case CPOINTER:
2996 SPEC_OCLS (spec) = code;
2997 break;
2999 case IPOINTER:
3000 SPEC_OCLS (spec) = idata;
3001 break;
3003 case PPOINTER:
3004 SPEC_OCLS (spec) = xstack;
3005 break;
3007 case EEPPOINTER:
3008 SPEC_OCLS (spec) = eeprom;
3009 break;
3011 default:
3012 break;
3016 /*-----------------------------------------------------------------*/
3017 /* geniCodeDerefPtr - dereference pointer with '*' */
3018 /*-----------------------------------------------------------------*/
3019 operand *
3020 geniCodeDerefPtr (operand *op, int lvl)
3022 sym_link *rtype, *retype;
3023 sym_link *optype = operandType (op);
3025 // if this is an array then array access
3026 if (IS_ARRAY (optype))
3028 // don't worry, this will be optimized out later
3029 return geniCodeArray (op, operandFromLit (0), lvl, false);
3032 // just in case someone screws up
3033 wassert (IS_PTR (optype));
3035 if (IS_TRUE_SYMOP (op))
3037 op->isaddr = 1;
3038 op = geniCodeRValue (op, TRUE);
3040 else if (IS_OP_LITERAL (op))
3042 /* To avoid problems converting a dereferenced literal pointer */
3043 /* back and forth between lvalue and rvalue formats, replace */
3044 /* the literal pointer with an iTemp and assign the literal */
3045 /* value to the iTemp. */
3046 iCode *ic;
3047 operand *iop = newiTempOperand (optype, 0);
3048 SPEC_SCLS (OP_SYM_ETYPE (iop)) = S_AUTO; /* remove S_LITERAL */
3049 iop->isaddr = 0; /* assign to the iTemp itself */
3050 ic = newiCode ('=', NULL, op);
3051 IC_RESULT (ic) = iop;
3052 ADDTOCHAIN (ic);
3053 op = operandFromOperand (iop); /* now use the iTemp as operand */
3054 optype = operandType (op);
3057 /* now get rid of the pointer part */
3058 if (isLvaluereq (lvl) && IS_ITEMP (op))
3060 retype = getSpec (rtype = copyLinkChain (optype));
3062 else
3064 retype = getSpec (rtype = copyLinkChain (optype->next));
3065 /* outputclass needs 2b updated */
3066 setOClass (optype, retype);
3069 op->isGptr = IS_GENPTR (optype);
3071 op->isaddr = (IS_PTR (rtype) ||
3072 IS_STRUCT (rtype) || IS_INT (rtype) || IS_BITINT (rtype) || IS_BOOL (rtype) || IS_CHAR (rtype) || IS_FLOAT (rtype) || IS_FIXED (rtype));
3074 if (!isLvaluereq (lvl))
3075 op = geniCodeRValue (op, TRUE);
3077 if (IS_DECL (rtype))
3079 DCL_PTR_ADDRSPACE (rtype) = 0;
3080 DCL_PTR_VOLATILE (rtype) = 0;
3082 else
3084 SPEC_ADDRSPACE (rtype) = 0;
3085 SPEC_VOLATILE (rtype) = 0;
3087 setOperandType (op, rtype);
3089 return op;
3092 /*-----------------------------------------------------------------*/
3093 /* geniCodeUnaryMinus - does a unary minus of the operand */
3094 /*-----------------------------------------------------------------*/
3095 operand *
3096 geniCodeUnaryMinus (operand * op)
3098 iCode *ic;
3099 sym_link *optype = operandType (op);
3101 if (IS_LITERAL (optype))
3102 return operandFromLit (-floatFromVal (OP_VALUE (op)));
3104 ic = newiCode (UNARYMINUS, op, NULL);
3105 IC_RESULT (ic) = newiTempOperand (optype, 0);
3106 ADDTOCHAIN (ic);
3107 return IC_RESULT (ic);
3110 /*-----------------------------------------------------------------*/
3111 /* geniCodeLeftShift - gen i code for left shift */
3112 /*-----------------------------------------------------------------*/
3113 operand *
3114 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
3116 iCode *ic;
3117 sym_link *resType;
3119 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
3120 ic = newiCode(LEFT_OP, left, right);
3121 IC_RESULT (ic) = newiTempOperand (resType, 0);
3122 ADDTOCHAIN (ic);
3123 return IC_RESULT (ic);
3126 /*-----------------------------------------------------------------*/
3127 /* geniCodeRightShift - gen i code for right shift */
3128 /*-----------------------------------------------------------------*/
3129 operand *
3130 geniCodeRightShift (operand * left, operand * right)
3132 iCode *ic;
3134 ic = newiCode (RIGHT_OP, left, right);
3135 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3136 ADDTOCHAIN (ic);
3137 return IC_RESULT (ic);
3140 /*-----------------------------------------------------------------*/
3141 /* geniCodeLogic- logic code */
3142 /*-----------------------------------------------------------------*/
3143 static operand *
3144 geniCodeLogic (operand * left, operand * right, int op, ast * tree)
3146 iCode *ic;
3147 sym_link *ctype, *ttype;
3148 sym_link *rtype = operandType (right);
3149 sym_link *ltype = operandType (left);
3151 /* left is integral type and right is literal then
3152 check if the literal value is within bounds */
3153 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
3155 CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
3156 switch (ccr_result)
3158 case CCR_ALWAYS_TRUE:
3159 case CCR_ALWAYS_FALSE:
3160 werror (W_COMP_RANGE, "true resp. false");
3161 return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
3162 default:
3163 break;
3167 /* Avoid expensive comparisons when the type of the constant is bigger than the type of the non-const operand */
3168 if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype) && getSize (ltype) < getSize (rtype))
3169 right->svt.valOperand = valCastLiteral (ltype, operandLitValue (right), operandLitValueUll (right));
3170 if (IS_INTEGRAL (rtype) && IS_LITERAL (ltype) && getSize (rtype) < getSize (ltype))
3171 left->svt.valOperand = valCastLiteral (rtype, operandLitValue (left), operandLitValueUll (left));
3173 /* if one operand is a pointer and the other is a literal generic void pointer,
3174 change the type of the literal generic void pointer to match the other pointer */
3175 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left) && IS_PTR (rtype) && !IS_GENPTR (rtype))
3177 /* find left's definition */
3178 ic = iCodeChain;
3179 while (ic)
3181 if (((ic->op == CAST) || (ic->op == '=')) && isOperandEqual (left, IC_RESULT (ic)))
3182 break;
3183 else
3184 ic = ic->next;
3186 /* if casting literal to generic pointer, then cast to rtype instead */
3187 if (ic && (ic->op == CAST) && isOperandLiteral (IC_RIGHT (ic)))
3189 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic)),operandLitValueUll (IC_RIGHT (ic))), false);
3190 ltype = operandType (left);
3193 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right) && IS_PTR (ltype) && !IS_GENPTR (ltype))
3195 /* find right's definition */
3196 ic = iCodeChain;
3197 while (ic)
3199 if (((ic->op == CAST) || (ic->op == '=')) && isOperandEqual (right, IC_RESULT (ic)))
3200 break;
3201 else
3202 ic = ic->next;
3204 /* if casting literal to generic pointer, then cast to rtype instead */
3205 if (ic && (ic->op == CAST) && isOperandLiteral (IC_RIGHT (ic)))
3207 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic)), operandLitValueUll (IC_RIGHT (ic))), false);
3208 rtype = operandType (right);
3212 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_BOOL, op);
3214 ic = newiCode (op, left, right);
3215 /* store 0 or 1 in result */
3216 ttype = (tree && IS_BOOLEAN (tree->ftype)) ? newBoolLink () : newCharLink ();
3217 IC_RESULT (ic) = newiTempOperand (ttype, 1);
3219 /* if comparing float
3220 and not a '==' || '!=' || '&&' || '||' (these
3221 will be inlined */
3222 if (IS_FLOAT (ctype) && op != EQ_OP && op != NE_OP && op != AND_OP && op != OR_OP)
3223 ic->supportRtn = 1;
3225 /* if comparing a fixed type use support functions */
3226 if (IS_FIXED (ctype))
3227 ic->supportRtn = 1;
3229 ADDTOCHAIN (ic);
3230 return IC_RESULT (ic);
3233 /*-----------------------------------------------------------------*/
3234 /* geniCodeLogicAndOr - && || operations */
3235 /*-----------------------------------------------------------------*/
3236 static operand *
3237 geniCodeLogicAndOr (ast * tree, int lvl)
3239 iCode *ic;
3240 sym_link *type;
3241 symbol *falseLabel = newiTempLabel (NULL);
3242 symbol *trueLabel = newiTempLabel (NULL);
3243 symbol *exitLabel = newiTempLabel (NULL);
3244 operand *op, *result, *condition;
3246 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3247 They can be reenabled by executing the following block. If you find
3248 a decent optimization you could start right here:
3250 #if 0
3251 if (0)
3253 operand *leftOp, *rightOp;
3255 leftOp = geniCodeRValue (ast2iCode (tree->left, lvl + 1), FALSE);
3256 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3258 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3260 #endif
3262 /* generate two IFX for the '&&' or '||' op */
3264 /* evaluate left operand */
3265 condition = ast2iCode (tree->left, lvl + 1);
3266 op = geniCodeRValue (condition, FALSE);
3268 /* test left operand */
3269 if (tree->opval.op == AND_OP)
3270 ic = newiCodeCondition (op, NULL, falseLabel);
3271 else /* OR_OP */
3272 ic = newiCodeCondition (op, trueLabel, NULL);
3273 ADDTOCHAIN (ic);
3275 /* evaluate right operand */
3276 condition = ast2iCode (tree->right, lvl + 1);
3277 op = geniCodeRValue (condition, FALSE);
3279 /* test right operand */
3280 ic = newiCodeCondition (op, trueLabel, NULL);
3281 ADDTOCHAIN (ic);
3283 /* store 0 or 1 in result */
3284 type = (IS_BOOLEAN (tree->ftype)) ? newBoolLink () : newCharLink ();
3285 result = newiTempOperand (type, 1);
3287 geniCodeLabel (falseLabel);
3288 geniCodeAssign (result, operandFromLit (0), 0, 0);
3289 /* generate an unconditional goto */
3290 geniCodeGoto (exitLabel);
3292 geniCodeLabel (trueLabel);
3293 geniCodeAssign (result, operandFromLit (1), 0, 0);
3295 geniCodeLabel (exitLabel);
3297 return result;
3300 /*-----------------------------------------------------------------*/
3301 /* geniCodeUnary - for a generic unary operation */
3302 /*-----------------------------------------------------------------*/
3303 operand *
3304 geniCodeUnary (operand * op, int oper, sym_link * resType)
3306 iCode *ic = newiCode (oper, op, NULL);
3308 IC_RESULT (ic) = newiTempOperand (resType, 0);
3309 ADDTOCHAIN (ic);
3310 return IC_RESULT (ic);
3313 /*-----------------------------------------------------------------*/
3314 /* geniCodeBinary - for a generic binary operation */
3315 /*-----------------------------------------------------------------*/
3316 operand *
3317 geniCodeBinary (operand * left, operand * right, int oper, sym_link * resType)
3319 iCode *ic = newiCode (oper, left, right);
3321 IC_RESULT (ic) = newiTempOperand (resType, 0);
3322 ADDTOCHAIN (ic);
3323 return IC_RESULT (ic);
3326 /*-----------------------------------------------------------------*/
3327 /* geniCodeConditional - geniCode for '?' ':' operation */
3328 /*-----------------------------------------------------------------*/
3329 operand *
3330 geniCodeConditional (ast * tree, int lvl)
3332 iCode *ic;
3333 symbol *falseLabel = newiTempLabel (NULL);
3334 symbol *exitLabel = newiTempLabel (NULL);
3335 ast *astTrue = tree->right->left;
3336 ast *astFalse = tree->right->right;
3337 operand *cond = ast2iCode (tree->left, lvl + 1);
3338 operand *result = newiTempOperand (tree->ftype, 0);
3339 operand *opTrue, *opFalse;
3341 ic = newiCodeCondition (geniCodeRValue (cond, FALSE), NULL, falseLabel);
3342 ADDTOCHAIN (ic);
3344 opTrue = ast2iCode (astTrue, lvl + 1);
3346 /* move the value to the new operand */
3347 geniCodeAssign (result, geniCodeRValue (opTrue, FALSE), 0, 0);
3349 /* generate an unconditional goto */
3350 geniCodeGoto (exitLabel);
3352 /* now for the right side */
3353 geniCodeLabel (falseLabel);
3355 opFalse = ast2iCode (astFalse, lvl + 1);
3356 geniCodeAssign (result, geniCodeRValue (opFalse, FALSE), 0, 0);
3358 /* create the exit label */
3359 geniCodeLabel (exitLabel);
3361 return result;
3364 /*-----------------------------------------------------------------*/
3365 /* checkTypes - check types for assignment */
3366 /*-----------------------------------------------------------------*/
3367 static operand *
3368 checkTypes (operand * left, operand * right)
3370 sym_link *ltype = operandType (left);
3371 sym_link *rtype = operandType (right);
3372 bool always_cast = FALSE;
3374 /* if the left & right type don't exactly match */
3375 /* if pointer set then make sure the check is
3376 done with the type & not the pointer */
3377 /* then cast rights type to left */
3379 /* first check the type for pointer assignment */
3380 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) && compareType (ltype, rtype, false) <= 0)
3382 if (left->aggr2ptr)
3384 always_cast = TRUE;
3386 else
3388 ltype = ltype->next;
3392 /* left is integral type and right is literal then
3393 check if the literal value is within bounds */
3394 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
3395 checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL)
3397 werror (W_LIT_OVERFLOW);
3400 if (always_cast || compareType (ltype, rtype, false) == -1)
3402 if (IS_VOLATILE (ltype)) // Don't propagate volatile to right side - we don't want volatile iTemps.
3404 ltype = copyLinkChain (ltype);
3405 if (IS_DECL(ltype))
3406 DCL_PTR_VOLATILE (ltype) = 0;
3407 else
3408 SPEC_VOLATILE (ltype) = 0;
3410 right = geniCodeCast (ltype, right, TRUE);
3412 checkPtrQualifiers (ltype, rtype, !right->isConstElimnated);
3413 return right;
3416 /*-----------------------------------------------------------------*/
3417 /* geniCodeAssign - generate code for assignment */
3418 /*-----------------------------------------------------------------*/
3419 operand *
3420 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3422 iCode *ic;
3423 sym_link *ltype;
3425 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3427 werror (E_LVALUE_REQUIRED, "assignment");
3428 return left;
3431 right = checkTypes (left, right);
3433 /* If left is a true symbol & ! volatile
3434 create an assignment to temporary for
3435 the right & then assign this temporary
3436 to the symbol. This is SSA (static single
3437 assignment). Isn't it simple and folks have
3438 published mountains of paper on it */
3439 if (IS_TRUE_SYMOP (left) && !isOperandVolatile (left, FALSE) && isOperandGlobal (left))
3441 symbol *sym = NULL;
3442 operand *newRight;
3443 sym_link *ltype = operandType (left);
3445 if (IS_TRUE_SYMOP (right))
3446 sym = OP_SYMBOL (right);
3447 ic = newiCode ('=', NULL, right);
3448 IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
3449 /* avoid double fetch from volatile right, see bug 1369874 */
3450 if (!isOperandVolatile (right, FALSE))
3451 SPIL_LOC (newRight) = sym;
3452 right = newRight;
3453 ADDTOCHAIN (ic);
3456 ic = newiCode ('=', NULL, right);
3457 IC_RESULT (ic) = left;
3458 ADDTOCHAIN (ic);
3460 /* if left isgptr flag is set then support
3461 routine will be required */
3462 if (left->isGptr)
3463 ic->supportRtn = 1;
3465 ic->nosupdate = nosupdate;
3466 /* left could be a pointer assignment,
3467 return the properly casted right instead */
3468 ltype = operandType (left);
3469 if ((IS_PTR (ltype) && IS_BITVAR (ltype->next)) || IS_BITVAR (ltype))
3470 return left;
3471 else
3472 return right;
3475 /*-----------------------------------------------------------------*/
3476 /* geniCodeDummyRead - generate code for dummy read */
3477 /*-----------------------------------------------------------------*/
3478 static void
3479 geniCodeDummyRead (operand * op)
3481 iCode *ic;
3482 sym_link *type = operandType (op);
3484 if (!IS_VOLATILE (type))
3485 return;
3487 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3488 ADDTOCHAIN (ic);
3490 ic->nosupdate = 1;
3493 /*-----------------------------------------------------------------*/
3494 /* geniCodeSEParms - generate code for side effecting fcalls */
3495 /*-----------------------------------------------------------------*/
3496 static void
3497 geniCodeSEParms (ast *parms, int lvl)
3499 if (!parms)
3500 return;
3502 if (IS_AST_PARAM (parms))
3504 geniCodeSEParms (parms->left, lvl);
3505 geniCodeSEParms (parms->right, lvl);
3506 return;
3509 /* hack don't like this but too lazy to think of
3510 something better */
3511 if (IS_ADDRESS_OF_OP (parms))
3512 parms->left->lvalue = 1;
3514 if (IS_CAST_OP (parms) && IS_PTR (parms->ftype) && IS_ADDRESS_OF_OP (parms->right))
3515 parms->right->left->lvalue = 1;
3517 if (parms->type == EX_OP && parms->opval.op == '[' && IS_STRUCT (parms->ftype)) // Do not dereference pointer to struct.
3518 parms->opval.op = '+';
3520 parms->opval.oprnd = geniCodeRValue (ast2iCode (parms, lvl + 1), FALSE);
3521 parms->type = EX_OPERAND;
3522 AST_ARGREG (parms) = parms->etype ? SPEC_ARGREG (parms->etype) : SPEC_ARGREG (parms->ftype);
3525 /*-----------------------------------------------------------------*/
3526 /* geniCodeParms - generates parameters */
3527 /*-----------------------------------------------------------------*/
3528 value *
3529 geniCodeParms (ast *parms, value *argVals, int *iArg, int *stack, sym_link *ftype, int lvl, iCode *iic_start)
3531 iCode *ic;
3532 operand *pval;
3534 if (!parms)
3535 return argVals;
3537 if (!iic_start)
3538 iic_start = iCodeChainEnd;
3540 /* if this is a param node then do the left & right */
3541 if (parms->type == EX_OP && parms->opval.op == PARAM)
3543 argVals = geniCodeParms (parms->left, argVals, iArg, stack, ftype, lvl, iic_start);
3544 argVals = geniCodeParms (parms->right, argVals, iArg, stack, ftype, lvl, iic_start);
3545 return argVals;
3548 // Get the parameter value. All the real work for this was done in geniCodeSEParms already.
3549 wassert (parms->type == EX_OPERAND);
3550 pval = parms->opval.oprnd;
3552 /* if register parm then make it a send */
3553 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS (ftype)) || IFFUNC_ISBUILTIN (ftype))
3555 pval = checkTypes (operandFromValue (argVals, true), pval);
3556 ic = newiCode (SEND, pval, NULL);
3557 ic->argreg = SPEC_ARGREG (parms->etype);
3558 ic->builtinSEND = FUNC_ISBUILTIN (ftype);
3559 ADDTOCHAIN (ic);
3561 else
3563 iCode *castic_start = 0;
3564 iCode *castic_end = 0;
3565 bool is_structparm = IS_STRUCT (parms->ftype); // struct parameter handling is hackish.
3566 if (iic_start != iCodeChainEnd)
3567 castic_start = iCodeChainEnd;
3568 if (is_structparm)
3570 sym_link *ptr = newLink (DECLARATOR);
3571 DCL_TYPE (ptr) = PTR_TYPE (SPEC_OCLS (getSpec (operandType (pval))));
3572 ptr->next = copyLinkChain (parms->ftype);
3573 if (IS_PTR (operandType (pval)))
3575 pval = geniCodeCast (ptr, pval, true);
3577 setOperandType (pval, ptr);
3579 // now decide whether to push or assign
3580 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3582 if (is_structparm) // Passing the parameter requires a memcpy.
3584 iCode *dstic, *srcic, *nic, *callic, *iic_end;
3585 // Keep this one in mind in so we can move it later.
3586 operand *dstop = geniCodeCast (FUNC_ARGS(builtin_memcpy->type)->type, operandFromValue (argVals, true), false);
3587 castic_end = iCodeChainEnd;
3588 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->etype))
3590 dstic = newiCode (SEND, dstop, 0);
3591 dstic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->etype);
3593 else
3595 dstic = newiCode ('=', 0, dstop);
3596 IC_RESULT (dstic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type), false);
3598 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->next->etype))
3600 srcic = newiCode (SEND, pval, 0);
3601 srcic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->next->etype);
3603 else
3605 srcic = newiCode ('=', 0, pval);
3606 IC_RESULT (srcic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type)->next, false);
3608 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->next->next->etype))
3610 nic = newiCode (SEND, operandFromLit (getSize (parms->ftype)), 0);
3611 nic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->next->next->etype);
3613 else
3615 nic = newiCode ('=', 0, operandFromLit (getSize (parms->ftype)));
3616 IC_RESULT (nic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type)->next->next, false);
3618 callic = newiCode (CALL, operandFromSymbol (builtin_memcpy, false), 0);
3619 IC_RESULT (callic) = newiTempOperand (builtin_memcpy->type->next, 0);
3620 // Insert before passing any other parameters - otherwise register parameters to the function will instead end up as parameters to the memcpy call.
3621 if (castic_start)
3623 iCode *castic = castic_start->next;
3624 // Cut out cast from where it is.
3625 castic_start->next = castic_end->next;
3626 if (castic_end->next)
3627 castic_end->next->prev = castic_start;
3628 if (castic_end == iCodeChainEnd)
3629 iCodeChainEnd = castic_start;
3630 // Insert it earlier.
3631 iic_end = iic_start->next;
3632 iic_start->next = castic;
3633 castic->prev = iic_start;
3634 castic_end->next = iic_end;
3635 if (iic_end)
3636 iic_end->prev = castic_end;
3638 iic_start = castic_end;
3639 iic_end = iic_start->next;
3640 iic_start->next = dstic;
3641 dstic->prev = iic_start;
3642 dstic->next = srcic;
3643 srcic->prev = dstic;
3644 srcic->next = nic;
3645 nic->prev = srcic;
3646 nic->next = callic;
3647 callic->prev = nic;
3648 callic->next = iic_end;
3649 if (iic_end)
3650 iic_end->prev = callic;
3651 else if (iic_start == iCodeChainEnd)
3652 iCodeChainEnd = callic;
3654 else
3656 // assign
3657 operand *top = operandFromValue (argVals, true);
3658 // clear useDef and other bitVectors
3659 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL (top)->clashes = 0;
3660 geniCodeAssign (top, pval, 1, 0);
3663 else
3665 if (argVals && (*iArg >= 0))
3666 pval = checkTypes (operandFromValue (argVals, false), pval);
3667 // push
3668 if (is_structparm)
3669 ic = newiCode (IPUSH_VALUE_AT_ADDRESS, pval, operandFromLit (0));
3670 else
3671 ic = newiCode (IPUSH, pval, NULL);
3672 ic->parmPush = 1;
3673 // update the stack adjustment
3674 sym_link *parmtype = IS_ARRAY (parms->ftype) ? aggrToPtr (parms->ftype, false) : parms->ftype;
3675 *stack += getSize (parmtype);
3676 if (IFFUNC_ISSMALLC (ftype) && getSize (parmtype) == 1) // SmallC calling convention passes 8-bit parameters as 16-bit values.
3677 (*stack)++;
3678 if (TARGET_PDK_LIKE && getSize (parmtype) % 2) // So does pdk due to stack alignment requirements.
3679 (*stack)++;
3680 ADDTOCHAIN (ic);
3684 if (*iArg >= 0)
3686 assert (argVals != NULL);
3687 argVals = argVals->next;
3689 (*iArg)++;
3690 return argVals;
3693 /*-----------------------------------------------------------------*/
3694 /* geniCodeCall - generates temp code for calling */
3695 /*-----------------------------------------------------------------*/
3696 operand *
3697 geniCodeCall (operand * left, ast * parms, int lvl)
3699 iCode *ic;
3700 sym_link *type, *etype;
3701 sym_link *ftype;
3702 int stack = 0;
3703 int iArg = 0;
3705 if (IS_ARRAY (operandType (left)))
3707 iCode *tic;
3708 sym_link *ttype;
3710 tic = newiCode (GET_VALUE_AT_ADDRESS, left, operandFromLit (0));
3711 ttype = copyLinkChain (operandType (left)->next);
3712 IC_RESULT (tic) = newiTempOperand (ttype, 1);
3713 IC_RESULT (tic)->isaddr = IS_FUNCPTR (ttype) ? 1 : 0;
3714 ADDTOCHAIN (tic);
3715 left = IC_RESULT (tic);
3718 ftype = operandType (left);
3719 if (!IS_FUNC (ftype) && !IS_FUNCPTR (ftype))
3721 werror (E_FUNCTION_EXPECTED);
3722 return operandFromValue (valueFromLit (0), false);
3725 // C2X unreachable. Just omit the call for now. TODO: Optimize based on this (remove preceding and subsequent icodes, up to whole basic block when no side effects)
3726 if (!IS_FUNCPTR (ftype) && !strcmp(OP_SYMBOL (left)->name, "__builtin_unreachable"))
3727 return 0;
3729 // not allow call a critical function
3730 if (inCriticalPair && FUNC_ISCRITICAL (ftype))
3731 werror (E_INVALID_CRITICAL);
3733 /* take care of parameters with side-effecting
3734 function calls in them, this is required to take care
3735 of overlaying function parameters */
3736 geniCodeSEParms (parms, lvl);
3738 if (IS_FUNCPTR (ftype))
3739 ftype = ftype->next;
3741 /* first the parameters */
3742 if ((options.stackAuto || IFFUNC_ISREENT (ftype)) && !IFFUNC_ISBUILTIN (ftype))
3744 value *argVals;
3745 int nArgs = 0;
3746 ast *parm;
3747 int nParms = 0;
3749 //count expected arguments except varargs
3750 for (argVals = FUNC_ARGS (ftype); argVals; argVals = argVals->next)
3751 nArgs++;
3752 //count actual parameters including varargs
3753 for (parm = parms; parm && parm->type == EX_OP && parm->opval.op == PARAM; parm = parm->right)
3755 if (parm->left)
3756 nParms++;
3758 if (parm)
3759 nParms++;
3760 argVals = FUNC_ARGS (ftype);
3761 iArg = nArgs - nParms;
3763 // reverse the argVals to match the parms
3764 argVals = reverseVal (argVals);
3765 geniCodeParms (parms, argVals, &iArg, &stack, ftype, lvl, 0);
3766 argVals = reverseVal (argVals);
3768 else
3770 geniCodeParms (parms, FUNC_ARGS (ftype), &iArg, &stack, ftype, lvl, 0);
3773 /* now call : if symbol then pcall */
3774 if (IS_OP_POINTER (left) || IS_ITEMP (left))
3776 ic = newiCode (PCALL, left, NULL);
3778 else
3780 ic = newiCode (CALL, left, NULL);
3783 type = copyLinkChain (ftype->next);
3784 etype = getSpec (type);
3785 SPEC_EXTR (etype) = 0;
3787 ADDTOCHAIN (ic);
3789 /* stack adjustment after call */
3790 ic->parmBytes = stack;
3792 if (!IS_STRUCT (type))
3794 IC_RESULT (ic) = newiTempOperand (type, 1);
3795 return IC_RESULT (ic);
3797 else
3799 symbol *sym = newSymbol (genSymName (ic->level), 1);
3800 sym->type = copyLinkChain (type);
3801 sym->etype = getSpec (sym->type);
3802 SPEC_SCLS (sym->etype) = S_AUTO;
3803 SPEC_OCLS (sym->etype) = NULL;
3804 SPEC_EXTR (sym->etype) = 0;
3805 SPEC_STAT (sym->etype) = 0;
3806 stack = allocVariables (sym);
3807 currFunc->stack += options.useXstack ? 0 : stack;
3808 currFunc->xstack += options.useXstack ? stack : 0;
3809 IC_RESULT (ic) = operandFromSymbol (sym, false);
3810 return (operandFromSymbol (sym, true));
3814 /*-----------------------------------------------------------------*/
3815 /* geniCodeReceive - generate intermediate code for "receive" */
3816 /*-----------------------------------------------------------------*/
3817 static void
3818 geniCodeReceive (value * args, operand * func)
3820 unsigned char paramByteCounter = 0;
3822 /* for all arguments that are passed in registers */
3823 while (args)
3825 if (IS_REGPARM (args->etype))
3827 operand *opr = operandFromValue (args, true);
3828 operand *opl;
3829 symbol *sym = OP_SYMBOL (opr);
3830 iCode *ic;
3832 /* we will use it after all optimizations
3833 and before liveRange calculation */
3834 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3837 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE) &&
3838 options.stackAuto == 0 && (!(options.model == MODEL_FLAT24)))
3841 else
3843 opl = newiTempOperand (args->type, 0);
3844 sym->reqv = opl;
3845 sym->reqv->key = sym->key;
3846 OP_SYMBOL (sym->reqv)->key = sym->key;
3847 OP_SYMBOL (sym->reqv)->isreqv = 1;
3848 OP_SYMBOL (sym->reqv)->islocal = 0;
3849 SPIL_LOC (sym->reqv) = sym;
3853 ic = newiCode (RECEIVE, func, NULL);
3854 ic->argreg = SPEC_ARGREG (args->etype);
3855 if (ic->argreg == 1)
3857 currFunc->recvSize = getSize (sym->type);
3859 IC_RESULT (ic) = opr;
3861 /* misuse of parmBytes (normally used for functions)
3862 * to save estimated stack position of this argument.
3863 * Normally this should be zero for RECEIVE iCodes.
3864 * No idea if this causes side effects on other ports. - dw
3866 ic->parmBytes = paramByteCounter;
3868 /* what stack position do we have? */
3869 paramByteCounter += getSize (sym->type);
3871 ADDTOCHAIN (ic);
3874 args = args->next;
3878 /*-----------------------------------------------------------------*/
3879 /* geniCodeFunctionBody - create the function body */
3880 /*-----------------------------------------------------------------*/
3881 void
3882 geniCodeFunctionBody (ast * tree, int lvl)
3884 iCode *ic;
3885 operand *func;
3886 char *savefilename;
3887 int savelineno;
3888 short functionBlock;
3890 /* reset the auto generation */
3891 /* numbers */
3892 iTempNum = 0;
3893 iTempLblNum = 0;
3894 operandKey = 0;
3895 iCodeKey = 0;
3896 func = ast2iCode (tree->left, lvl + 1);
3898 savefilename = filename;
3899 savelineno = lineno;
3900 filename = OP_SYMBOL (func)->fileDef;
3901 lineno = OP_SYMBOL (func)->lineDef;
3902 /* create an entry label */
3903 geniCodeLabel (entryLabel);
3904 filename = savefilename;
3905 lineno = savelineno;
3907 /* create a proc icode */
3908 functionBlock = block;
3909 ic = newiCode (FUNCTION, func, NULL);
3910 filename = ic->filename = OP_SYMBOL (func)->fileDef;
3911 lineno = ic->lineno = OP_SYMBOL (func)->lineDef;
3912 ic->tree = tree;
3914 ADDTOCHAIN (ic);
3916 /* for all parameters that are passed
3917 on registers add a "receive" */
3918 geniCodeReceive (tree->values.args, func);
3920 /* generate code for the body */
3921 ast2iCode (tree->right, lvl + 1);
3923 /* create a label for return */
3924 block = functionBlock;
3925 geniCodeLabel (returnLabel);
3927 /* now generate the end proc */
3928 ic = newiCode (ENDFUNCTION, func, NULL);
3929 ic->filename = OP_SYMBOL (func)->fileDef;
3930 ic->lineno = OP_SYMBOL (func)->lastLine;
3931 ic->tree = tree;
3932 ADDTOCHAIN (ic);
3933 return;
3936 /*-----------------------------------------------------------------*/
3937 /* geniCodeReturn - gen icode for 'return' statement */
3938 /*-----------------------------------------------------------------*/
3939 void
3940 geniCodeReturn (operand * op)
3942 iCode *ic;
3944 /* return in _Noreturn function */
3945 if (currFunc && IFFUNC_ISNORETURN (currFunc->type))
3946 werror (W_NORETURNRETURN);
3948 /* check if a cast is needed */
3949 if (op && currFunc && currFunc->type && currFunc->type->next)
3950 checkPtrQualifiers (currFunc->type->next, operandType (op), !op->isConstElimnated);
3952 /* if the operand is present force an rvalue */
3953 if (op)
3954 op = geniCodeRValue (op, FALSE);
3956 ic = newiCode (RETURN, op, NULL);
3957 ADDTOCHAIN (ic);
3960 /*-----------------------------------------------------------------*/
3961 /* geniCodeIfx - generates code for extended if statement */
3962 /*-----------------------------------------------------------------*/
3963 void
3964 geniCodeIfx (ast * tree, int lvl)
3966 iCode *ic;
3967 operand *condition = ast2iCode (tree->left, lvl + 1);
3968 sym_link *cetype;
3970 /* if condition is null then exit */
3971 if (!condition)
3972 goto exit;
3973 else
3974 condition = geniCodeRValue (condition, FALSE);
3976 cetype = getSpec (operandType (condition));
3977 /* if the condition is a literal */
3978 if (IS_LITERAL (cetype))
3980 if (floatFromVal (OP_VALUE (condition)))
3982 if (tree->trueLabel)
3983 geniCodeGoto (tree->trueLabel);
3984 else
3985 assert (0);
3987 else
3989 if (tree->falseLabel)
3990 geniCodeGoto (tree->falseLabel);
3992 goto exit;
3995 if (tree->trueLabel)
3997 ic = newiCodeCondition (condition, tree->trueLabel, NULL);
3998 ADDTOCHAIN (ic);
4000 if (tree->falseLabel)
4001 geniCodeGoto (tree->falseLabel);
4003 else
4005 ic = newiCodeCondition (condition, NULL, tree->falseLabel);
4006 ADDTOCHAIN (ic);
4009 exit:
4010 if (tree->right && tree->right->type == EX_VALUE)
4011 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4012 else
4013 ast2iCode (tree->right, lvl + 1);
4016 /*-----------------------------------------------------------------*/
4017 /* geniCodeJumpTable - tries to create a jump table for switch */
4018 /*-----------------------------------------------------------------*/
4020 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
4022 int min, max, cnt = 1;
4023 int i, t;
4024 value *vch, *maxVal;
4025 iCode *ic;
4026 symbol *falseLabel;
4027 set *labels = NULL;
4028 sym_link *cetype = getSpec (operandType (cond));
4029 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
4030 int sizeofMatchJump, sizeofJumpTable;
4031 int sizeIndex;
4032 struct dbuf_s dbuf;
4034 if (!tree || !caseVals)
4035 return 0;
4037 /* the criteria for creating a jump table is */
4038 /* all integer numbers between the maximum & minimum must */
4039 /* be present, the maximum value should not exceed 255 */
4040 /* If not all integer numbers are present the algorithm */
4041 /* inserts jumps to the default label for the missing numbers */
4042 /* and decides later whether it is worth it */
4043 min = (int) ulFromVal (vch = caseVals);
4045 while (vch->next)
4047 cnt++;
4048 vch = vch->next;
4050 max = (int) ulFromVal (vch);
4051 maxVal = vch;
4053 if (max-min < 0)
4054 return 0;
4055 /* Exit if the range is too large to handle with a jump table. */
4056 if (1 + max - min > port->jumptableCost.maxCount)
4057 return 0;
4059 switch (getSize (operandType (cond)))
4061 case 1:
4062 sizeIndex = 0;
4063 break;
4064 case 2:
4065 sizeIndex = 1;
4066 break;
4067 case 4:
4068 sizeIndex = 2;
4069 break;
4070 default:
4071 return 0;
4074 /* Compute the size cost of the range check and subtraction. */
4075 sizeofMinCost = 0;
4076 sizeofZeroMinCost = 0;
4077 sizeofMaxCost = 0;
4079 if (!(min == 0 && IS_UNSIGNED (cetype)))
4080 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4081 if (!IS_UNSIGNED (cetype))
4082 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4083 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4085 if (min)
4086 sizeofMinCost += port->jumptableCost.sizeofSubtract;
4088 /* If the size cost of handling a non-zero minimum exceeds the */
4089 /* cost of extending the range down to zero, then it might be */
4090 /* better to extend the range to zero. */
4091 if (min > 0 && (sizeofMinCost - sizeofZeroMinCost) >= (min * port->jumptableCost.sizeofElement))
4093 /* Only extend the jump table if it would still be manageable. */
4094 if (1 + max <= port->jumptableCost.maxCount)
4096 min = 0;
4097 if (IS_UNSIGNED (cetype))
4098 sizeofMinCost = 0;
4099 else
4100 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4104 /* Compute the total size cost of a jump table. */
4105 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
4106 + port->jumptableCost.sizeofDispatch + sizeofMinCost + sizeofMaxCost;
4108 /* Compute the total size cost of a match & jump sequence */
4109 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
4111 /* If the size cost of the jump table is uneconomical then exit */
4112 if (sizeofMatchJump < sizeofJumpTable)
4113 return 0;
4115 /* The jump table is preferable. */
4117 /* First, a label for the default or missing cases. */
4118 dbuf_init (&dbuf, 128);
4119 if (tree->values.switchVals.swDefault)
4121 dbuf_printf (&dbuf, "_default_%d%s", tree->values.switchVals.swNum,
4122 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4124 else
4126 dbuf_printf (&dbuf, "_swBrk_%d%s", tree->values.switchVals.swNum,
4127 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4129 falseLabel = newiTempLabel (dbuf_c_str (&dbuf));
4130 dbuf_destroy (&dbuf);
4132 /* Build the list of labels for the jump table. */
4133 vch = caseVals;
4134 t = (int) ulFromVal (vch);
4135 for (i = min; i <= max; i++)
4137 if (vch && t == i)
4139 dbuf_init (&dbuf, 128);
4140 /* Explicit case: make a new label for it. */
4141 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, i,
4142 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4143 addSet (&labels, newiTempLabel (dbuf_c_str (&dbuf)));
4144 dbuf_destroy (&dbuf);
4145 vch = vch->next;
4146 if (vch)
4147 t = (int) ulFromVal (vch);
4149 else
4151 /* Implicit case: use the default label. */
4152 addSet (&labels, falseLabel);
4156 /* first we rule out the boundary conditions */
4158 operand *lit;
4159 operand *boundary;
4160 sym_link *cetype = getSpec (operandType (cond));
4161 /* no need to check the lower bound if
4162 the condition is always >= min or
4163 the condition is unsigned & minimum value is zero */
4164 if ((checkConstantRange (cetype, caseVals->etype, '<', FALSE) != CCR_ALWAYS_FALSE) &&
4165 (!(min == 0 && IS_UNSIGNED (cetype))))
4167 lit = operandFromValue (valCastLiteral (cetype, min, min), false);
4168 boundary = geniCodeLogic (cond, lit, '<', NULL);
4169 ic = newiCodeCondition (boundary, falseLabel, NULL);
4170 ADDTOCHAIN (ic);
4173 /* now for upper bounds */
4174 if (checkConstantRange (cetype, maxVal->etype, '>', FALSE) != CCR_ALWAYS_FALSE)
4176 lit = operandFromValue (valCastLiteral (cetype, max, max), false);
4177 boundary = geniCodeLogic (cond, lit, '>', NULL);
4178 ic = newiCodeCondition (boundary, falseLabel, NULL);
4179 ADDTOCHAIN (ic);
4183 /* if the min is not zero then we now make it zero */
4184 if (min)
4186 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
4187 if (!IS_LITERAL (getSpec (operandType (cond))))
4188 setOperandType (cond, UCHARTYPE);
4191 /* now create the jumptable */
4192 ic = newiCode (JUMPTABLE, NULL, NULL);
4193 IC_JTCOND (ic) = cond;
4194 IC_JTLABELS (ic) = labels;
4195 ADDTOCHAIN (ic);
4196 return 1;
4199 /*-----------------------------------------------------------------*/
4200 /* geniCodeSwitch - changes a switch to a if statement */
4201 /*-----------------------------------------------------------------*/
4202 void
4203 geniCodeSwitch (ast * tree, int lvl)
4205 iCode *ic;
4206 operand *cond = geniCodeRValue (ast2iCode (tree->left, lvl + 1), FALSE);
4207 value *caseVals = tree->values.switchVals.swVals;
4208 symbol *trueLabel, *falseLabel;
4209 struct dbuf_s dbuf;
4211 /* If the condition is a literal, then just jump to the */
4212 /* appropriate case label. */
4213 if (IS_LITERAL (getSpec (operandType (cond))))
4215 int switchVal, caseVal;
4217 switchVal = (int) ulFromVal (OP_VALUE (cond));
4218 while (caseVals)
4220 caseVal = (int) ulFromVal (caseVals);
4221 if (caseVal == switchVal)
4223 struct dbuf_s dbuf;
4225 dbuf_init (&dbuf, 128);
4226 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, caseVal,
4227 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4228 trueLabel = newiTempLabel (dbuf_c_str (&dbuf));
4229 dbuf_destroy (&dbuf);
4230 geniCodeGoto (trueLabel);
4231 goto jumpTable;
4233 caseVals = caseVals->next;
4235 goto defaultOrBreak;
4238 /* If cond is volatile, it might change while we are trying to */
4239 /* find the matching case. To avoid this possibility, make a */
4240 /* non-volatile copy to use instead. */
4241 if (IS_OP_VOLATILE (cond))
4243 operand *newcond;
4244 iCode *ic;
4246 newcond = newiTempOperand (operandType (cond), TRUE);
4247 newcond->isvolatile = 0;
4248 ic = newiCode ('=', NULL, cond);
4249 IC_RESULT (ic) = newcond;
4250 ADDTOCHAIN (ic);
4251 cond = newcond;
4254 /* if we can make this a jump table */
4255 if (geniCodeJumpTable (cond, caseVals, tree))
4256 goto jumpTable; /* no need for the comparison */
4258 /* for the cases defined do */
4259 while (caseVals)
4261 operand *compare = geniCodeLogic (cond, operandFromValue (caseVals, true), EQ_OP, NULL);
4263 dbuf_init (&dbuf, 128);
4264 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, (int) ulFromVal (caseVals),
4265 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4266 trueLabel = newiTempLabel (dbuf_c_str (&dbuf));
4267 dbuf_destroy (&dbuf);
4269 ic = newiCodeCondition (compare, trueLabel, NULL);
4270 ADDTOCHAIN (ic);
4271 caseVals = caseVals->next;
4274 defaultOrBreak:
4275 /* if default is present then goto break else break */
4276 dbuf_init (&dbuf, 128);
4277 if (tree->values.switchVals.swDefault)
4279 dbuf_printf (&dbuf, "_default_%d%s", tree->values.switchVals.swNum,
4280 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4282 else
4284 dbuf_printf (&dbuf, "_swBrk_%d%s", tree->values.switchVals.swNum,
4285 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4288 falseLabel = newiTempLabel (dbuf_c_str (&dbuf));
4289 dbuf_destroy (&dbuf);
4290 geniCodeGoto (falseLabel);
4292 jumpTable:
4293 ast2iCode (tree->right, lvl + 1);
4296 /*-----------------------------------------------------------------*/
4297 /* geniCodeInline - intermediate code for inline assembler */
4298 /*-----------------------------------------------------------------*/
4299 static void
4300 geniCodeInline (ast * tree)
4302 iCode *ic;
4304 ic = newiCode (INLINEASM, NULL, NULL);
4305 IC_INLINE (ic) = tree->values.inlineasm;
4306 ADDTOCHAIN (ic);
4309 /*-----------------------------------------------------------------*/
4310 /* geniCodeArrayInit - intermediate code for array initializer */
4311 /*-----------------------------------------------------------------*/
4312 static void
4313 geniCodeArrayInit (ast * tree, operand * array)
4315 iCode *ic;
4317 if (!getenv ("TRY_THE_NEW_INITIALIZER"))
4319 ic = newiCode (ARRAYINIT, array, NULL);
4320 IC_ARRAYILIST (ic) = tree->values.constlist;
4322 else
4324 operand *left = newOperand (), *right = newOperand ();
4325 left->type = right->type = SYMBOL;
4326 OP_SYMBOL (left) = AST_SYMBOL (tree->left);
4327 OP_SYMBOL (right) = AST_SYMBOL (tree->right);
4328 ic = newiCode (ARRAYINIT, left, right);
4330 ADDTOCHAIN (ic);
4333 /*-----------------------------------------------------------------*/
4334 /* geniCodeCritical - intermediate code for a critical statement */
4335 /*-----------------------------------------------------------------*/
4336 static void
4337 geniCodeCritical (ast * tree, int lvl)
4339 iCode *ic;
4340 operand *op = NULL;
4341 sym_link *type;
4343 if (!options.stackAuto && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE)
4345 type = newLink (SPECIFIER);
4346 SPEC_VOLATILE (type) = 1;
4347 SPEC_NOUN (type) = V_BIT;
4348 SPEC_SCLS (type) = S_BIT;
4349 SPEC_BLEN (type) = 1;
4350 SPEC_BSTR (type) = 0;
4351 op = newiTempOperand (type, 1);
4354 /* If op is NULL, the original interrupt state will saved on */
4355 /* the stack. Otherwise, it will be saved in op. */
4357 /* Generate a save of the current interrupt state & disable */
4358 inCriticalPair = 1;
4359 ic = newiCode (CRITICAL, NULL, NULL);
4360 IC_RESULT (ic) = op;
4361 ADDTOCHAIN (ic);
4363 /* Generate the critical code sequence */
4364 if (tree->left && tree->left->type == EX_VALUE)
4365 geniCodeDummyRead (ast2iCode (tree->left, lvl + 1));
4366 else
4367 ast2iCode (tree->left, lvl + 1);
4369 /* Generate a restore of the original interrupt state */
4370 ic = newiCode (ENDCRITICAL, NULL, op);
4371 ADDTOCHAIN (ic);
4372 inCriticalPair = 0;
4375 /*-----------------------------------------------------------------*/
4376 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
4377 /* particular case. Ie : assigning or dereferencing array or ptr */
4378 /*-----------------------------------------------------------------*/
4379 set *lvaluereqSet = NULL;
4380 typedef struct lvalItem
4382 int req;
4383 int lvl;
4385 lvalItem;
4387 /*-----------------------------------------------------------------*/
4388 /* addLvaluereq - add a flag for lvalreq for current ast level */
4389 /*-----------------------------------------------------------------*/
4390 static void
4391 addLvaluereq (int lvl)
4393 lvalItem *lpItem = (lvalItem *) Safe_alloc (sizeof (lvalItem));
4394 lpItem->req = 1;
4395 lpItem->lvl = lvl;
4396 addSetHead (&lvaluereqSet, lpItem);
4399 /*-----------------------------------------------------------------*/
4400 /* delLvaluereq - del a flag for lvalreq for current ast level */
4401 /*-----------------------------------------------------------------*/
4402 static void
4403 delLvaluereq ()
4405 lvalItem *lpItem = getSet (&lvaluereqSet);
4406 if (lpItem)
4407 Safe_free (lpItem);
4410 /*-----------------------------------------------------------------*/
4411 /* clearLvaluereq - clear lvalreq flag */
4412 /*-----------------------------------------------------------------*/
4413 static void
4414 clearLvaluereq ()
4416 lvalItem *lpItem = peekSet (lvaluereqSet);
4417 if (lpItem)
4418 lpItem->req = 0;
4421 /*-----------------------------------------------------------------*/
4422 /* getLvaluereq - get the last lvalreq level */
4423 /*-----------------------------------------------------------------*/
4424 #if 0
4426 getLvaluereqLvl ()
4428 lvalItem *lpItem = peekSet (lvaluereqSet);
4429 if (lpItem)
4430 return lpItem->lvl;
4431 return 0;
4433 #endif
4434 /*-----------------------------------------------------------------*/
4435 /* isLvaluereq - is lvalreq valid for this level ? */
4436 /*-----------------------------------------------------------------*/
4437 static int
4438 isLvaluereq (int lvl)
4440 lvalItem *lpItem = peekSet (lvaluereqSet);
4441 if (lpItem)
4442 return ((lpItem->req) && (lvl <= (lpItem->lvl + 1)));
4443 return 0;
4446 /*-----------------------------------------------------------------*/
4447 /* ast2iCode - creates an icodeList from an ast */
4448 /*-----------------------------------------------------------------*/
4449 operand *
4450 ast2iCode (ast * tree, int lvl)
4452 operand *left = NULL;
4453 operand *right = NULL;
4454 if (!tree)
4455 return NULL;
4457 /* set the global variables for filename & line number */
4458 if (tree->filename)
4459 filename = tree->filename;
4460 if (tree->lineno)
4461 lineno = tree->lineno;
4462 if (tree->block)
4463 block = tree->block;
4464 if (tree->level)
4465 scopeLevel = tree->level;
4466 if (tree->seqPoint)
4467 seqPoint = tree->seqPoint;
4469 if (tree->type == EX_VALUE)
4470 return operandFromValue (tree->opval.val, true);
4472 if (tree->type == EX_LINK)
4473 return operandFromLink (tree->opval.lnk);
4475 /* if we find a nullop */
4476 if (tree->type == EX_OP && (tree->opval.op == NULLOP || tree->opval.op == BLOCK))
4478 int oldInlinedActive = inlinedActive;
4479 if (tree->inlined)
4480 inlinedActive = 1;
4481 if (tree->left && tree->left->type == EX_VALUE)
4482 geniCodeDummyRead (ast2iCode (tree->left, lvl + 1));
4483 else
4484 ast2iCode (tree->left, lvl + 1);
4485 if (tree->right && tree->right->type == EX_VALUE)
4486 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4487 else
4488 ast2iCode (tree->right, lvl + 1);
4489 inlinedActive = oldInlinedActive;
4490 return NULL;
4493 /* special cases for not evaluating */
4494 if (tree->opval.op != ':' &&
4495 tree->opval.op != '?' &&
4496 tree->opval.op != CALL &&
4497 tree->opval.op != IFX &&
4498 tree->opval.op != AND_OP &&
4499 tree->opval.op != OR_OP &&
4500 tree->opval.op != LABEL &&
4501 tree->opval.op != GOTO &&
4502 tree->opval.op != SWITCH && tree->opval.op != FUNCTION && tree->opval.op != INLINEASM && tree->opval.op != CRITICAL)
4504 if (IS_ASSIGN_OP (tree->opval.op) || IS_DEREF_OP (tree) || IS_ADDRESS_OF_OP (tree))
4506 addLvaluereq (lvl);
4507 if ((!IS_ADDRESS_OF_OP (tree) && IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left) &&
4508 tree->left->left->ftype && IS_ARRAY (tree->left->left->ftype) &&
4509 tree->left->left->ftype->next && IS_ARRAY (tree->left->left->ftype->next)) ||
4510 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4511 clearLvaluereq ();
4513 left = operandFromAst (tree->left, lvl, true);
4514 delLvaluereq ();
4515 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4516 left = geniCodeRValue (left, TRUE);
4518 else
4520 left = operandFromAst (tree->left, lvl, true);
4522 if (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)
4524 addLvaluereq (lvl);
4525 right = operandFromAst (tree->right, lvl, true);
4526 delLvaluereq ();
4528 else
4530 right = operandFromAst (tree->right, lvl, tree->opval.op != RETURN);
4534 /* now depending on the type of operand */
4535 /* this will be a biggy */
4536 switch (tree->opval.op)
4538 case '[': /* array operation */
4540 //sym_link *ltype = operandType (left);
4541 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4542 left = geniCodeRValue (left, FALSE);
4543 right = geniCodeRValue (right, TRUE);
4546 return geniCodeArray (left, right, lvl, false);
4548 case '.': /* structure dereference */
4549 if (IS_PTR (operandType (left)))
4550 left = geniCodeRValue (left, TRUE);
4551 else
4552 left = geniCodeRValue (left, FALSE);
4554 return geniCodeStruct (left, right, tree->lvalue);
4556 case PTR_OP: /* structure pointer dereference */
4558 sym_link *pType;
4559 pType = operandType (left);
4560 left = geniCodeRValue (left, TRUE);
4562 setOClass (pType, getSpec (operandType (left)));
4565 return geniCodeStruct (left, right, tree->lvalue);
4567 case INC_OP: /* increment operator */
4568 if (left)
4569 return geniCodePostInc (left);
4570 else
4571 return geniCodePreInc (right, tree->lvalue);
4573 case DEC_OP: /* decrement operator */
4574 if (left)
4575 return geniCodePostDec (left);
4576 else
4577 return geniCodePreDec (right, tree->lvalue);
4579 case '&': /* bitwise and or address of operator */
4580 if (right)
4581 { /* this is a bitwise operator */
4582 left = geniCodeRValue (left, FALSE);
4583 right = geniCodeRValue (right, FALSE);
4584 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4586 else
4587 return geniCodeAddressOf (left);
4589 case '|': /* bitwise or & xor */
4590 case '^':
4591 return geniCodeBitwise (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), tree->opval.op, tree->ftype);
4593 case '/':
4594 return geniCodeDivision (geniCodeRValue (left, FALSE),
4595 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), false);
4597 case '%':
4598 return geniCodeModulus (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4599 case '*':
4600 if (right)
4601 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4602 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4603 else
4604 return geniCodeDerefPtr (geniCodeRValue (left, FALSE), lvl);
4606 case '-':
4607 if (right)
4608 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4609 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4610 else
4611 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4613 case '+':
4614 if (right)
4615 return geniCodeAdd (geniCodeRValue (left, FALSE),
4616 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), lvl);
4617 else
4618 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4620 case LEFT_OP:
4621 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4622 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4624 case RIGHT_OP:
4625 return geniCodeRightShift (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE));
4626 case CAST:
4627 #if 0 // this indeed needs a second thought
4629 operand *op;
4631 // let's keep this simple: get the rvalue we need
4632 op = geniCodeRValue (right, FALSE);
4633 // now cast it to whatever we want
4634 op = geniCodeCast (operandType (left), op, FALSE);
4635 // if this is going to be used as an lvalue, make it so
4636 if (tree->lvalue)
4638 op->isaddr = 1;
4640 return op;
4642 #else // bug #604575, is it a bug ????
4643 return geniCodeCast (operandType (left), geniCodeRValue (right, FALSE), FALSE);
4644 #endif
4646 case '~':
4647 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op, tree->ftype);
4649 case '!':
4651 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op, tree->ftype);
4652 return op;
4654 case ROT:
4656 operand *op = geniCodeBinary (geniCodeRValue (left, false),
4657 geniCodeRValue (right, false),
4658 tree->opval.op, tree->ftype);
4659 return op;
4661 case GETABIT:
4663 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4664 geniCodeRValue (right, FALSE),
4665 tree->opval.op, tree->ftype);
4666 return op;
4668 case GETBYTE:
4670 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4671 geniCodeRValue (right, FALSE),
4672 tree->opval.op, tree->ftype);
4673 setOperandType (op, UCHARTYPE);
4674 return op;
4676 case GETWORD:
4678 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4679 geniCodeRValue (right, FALSE),
4680 tree->opval.op, tree->ftype);
4681 setOperandType (op, UINTTYPE);
4682 return op;
4684 case AND_OP:
4685 case OR_OP:
4686 return geniCodeLogicAndOr (tree, lvl);
4687 case '>':
4688 case '<':
4689 case LE_OP:
4690 case GE_OP:
4691 case EQ_OP:
4692 case NE_OP:
4693 /* different compilers (even different gccs) evaluate
4694 the two calls in a different order. to get the same
4695 result on all machines we have to specify a clear sequence.
4696 return geniCodeLogic (geniCodeRValue (left, FALSE),
4697 geniCodeRValue (right, FALSE),
4698 tree->opval.op);
4701 operand *leftOp, *rightOp;
4703 leftOp = geniCodeRValue (left, FALSE);
4704 rightOp = geniCodeRValue (right, FALSE);
4706 return geniCodeLogic (leftOp, rightOp, tree->opval.op, tree);
4708 case '?':
4709 return geniCodeConditional (tree, lvl);
4711 case SIZEOF:
4712 return operandFromLit (getSize (tree->right->ftype));
4714 case '=':
4716 sym_link *rtype = operandType (right);
4717 sym_link *ltype = operandType (left);
4718 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4719 right = geniCodeRValue (right, TRUE);
4720 else
4721 right = geniCodeRValue (right, FALSE);
4722 return geniCodeAssign (left, right, 0, 1);
4724 case MUL_ASSIGN:
4725 return
4726 geniCodeAssign (left,
4727 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4728 FALSE),
4729 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4731 case DIV_ASSIGN:
4732 return
4733 geniCodeAssign (left,
4734 geniCodeDivision (geniCodeRValue (operandFromOperand (left), FALSE),
4735 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), false), 0, 1);
4736 case MOD_ASSIGN:
4737 return
4738 geniCodeAssign (left,
4739 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4740 FALSE),
4741 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4742 case ADD_ASSIGN:
4744 sym_link *rtype = operandType (right);
4745 sym_link *ltype = operandType (left);
4746 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4747 right = geniCodeRValue (right, TRUE);
4748 else
4749 right = geniCodeRValue (right, FALSE);
4752 return geniCodeAssign (left,
4753 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4754 FALSE), right, getResultTypeFromType (tree->ftype), lvl), 0, 1);
4756 case SUB_ASSIGN:
4758 sym_link *rtype = operandType (right);
4759 sym_link *ltype = operandType (left);
4760 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4762 right = geniCodeRValue (right, TRUE);
4764 else
4766 right = geniCodeRValue (right, FALSE);
4768 return
4769 geniCodeAssign (left,
4770 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4771 FALSE), right, getResultTypeFromType (tree->ftype)), 0, 1);
4773 case LEFT_ASSIGN:
4774 return
4775 geniCodeAssign (left,
4776 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left), FALSE),
4777 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4778 case RIGHT_ASSIGN:
4779 return
4780 geniCodeAssign (left,
4781 geniCodeRightShift (geniCodeRValue (operandFromOperand (left), FALSE),
4782 geniCodeRValue (right, FALSE)), 0, 1);
4783 case AND_ASSIGN:
4784 return
4785 geniCodeAssign (left,
4786 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4787 FALSE),
4788 geniCodeRValue (right, FALSE), BITWISEAND, operandType (left)), 0, 1);
4789 case XOR_ASSIGN:
4790 return
4791 geniCodeAssign (left,
4792 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4793 FALSE), geniCodeRValue (right, FALSE), '^', operandType (left)), 0, 1);
4794 case OR_ASSIGN:
4795 return
4796 geniCodeAssign (left,
4797 geniCodeBitwise (geniCodeRValue (operandFromOperand (left), FALSE),
4798 geniCodeRValue (right, FALSE), '|', operandType (left)), 0, 1);
4799 case ',':
4800 return geniCodeRValue (right, FALSE);
4802 case CALL:
4803 return geniCodeCall (ast2iCode (tree->left, lvl + 1), tree->right, lvl);
4805 case LABEL:
4806 geniCodeLabel (OP_SYMBOL (ast2iCode (tree->left, lvl + 1)));
4807 if (tree->right && tree->right->type == EX_VALUE)
4809 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4810 return NULL;
4812 else
4813 return ast2iCode (tree->right, lvl + 1);
4815 case GOTO:
4816 geniCodeGoto (OP_SYMBOL (ast2iCode (tree->left, lvl + 1)));
4817 return ast2iCode (tree->right, lvl + 1);
4819 case FUNCTION:
4820 geniCodeFunctionBody (tree, lvl);
4821 return NULL;
4823 case RETURN:
4824 geniCodeReturn (right);
4825 return NULL;
4827 case IFX:
4828 geniCodeIfx (tree, lvl);
4829 return NULL;
4831 case SWITCH:
4832 geniCodeSwitch (tree, lvl);
4833 return NULL;
4835 case INLINEASM:
4836 geniCodeInline (tree);
4837 return NULL;
4839 case ARRAYINIT:
4840 geniCodeArrayInit (tree, ast2iCode (tree->left, lvl + 1));
4841 return NULL;
4843 case CRITICAL:
4844 geniCodeCritical (tree, lvl);
4847 return NULL;
4850 /*-----------------------------------------------------------------*/
4851 /* iCodeFromAst - given an ast will convert it to iCode */
4852 /*-----------------------------------------------------------------*/
4853 iCode *
4854 iCodeFromAst (ast * tree)
4856 returnLabel = newiTempLabel ("_return");
4857 entryLabel = newiTempLabel ("_entry");
4858 iCodeChain = 0;
4859 ast2iCode (tree, 0);
4860 return (iCodeChain);
4863 static const char *
4864 opTypeToStr (OPTYPE op)
4866 switch (op)
4868 case SYMBOL:
4869 return "symbol";
4870 case VALUE:
4871 return "value";
4872 case TYPE:
4873 return "type";
4875 return "undefined type";
4879 operand *
4880 validateOpType (operand *op, const char *macro, const char *args, OPTYPE type, const char *file, unsigned line)
4882 if (op && op->type == type)
4884 return op;
4886 fprintf (stderr,
4887 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4888 " expected %s, got %s\n", macro, args, file, line, opTypeToStr (type), op ? opTypeToStr (op->type) : "null op");
4889 exit (EXIT_FAILURE);
4890 return op; // never reached, makes compiler happy.
4893 const operand *
4894 validateOpTypeConst (const operand *op, const char *macro, const char *args, OPTYPE type, const char *file, unsigned line)
4896 if (op && op->type == type)
4898 return op;
4900 fprintf (stderr,
4901 "Internal error: validateOpTypeConst failed in %s(%s) @ %s:%u:"
4902 " expected %s, got %s\n", macro, args, file, line, opTypeToStr (type), op ? opTypeToStr (op->type) : "null op");
4903 exit (EXIT_FAILURE);
4904 return op; // never reached, makes compiler happy.