struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / src / SDCCicode.c
blob1ccf8900c3b7e05be243304fa1a49f0c97823438
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_ULONG) ulFromVal (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 ((p2 = powof2 ((TYPE_TARGET_ULONG) ulFromVal (OP_VALUE (right)))) > 0) &&
2304 (TARGET_Z80_LIKE || TARGET_HC08_LIKE || TARGET_MOS6502_LIKE))
2306 operand *tmp;
2307 symbol *label = newiTempLabel (NULL);
2309 tmp = newiTempOperand (ltype, 0);
2310 geniCodeAssign (tmp, left, 0, 0);
2312 ic = newiCodeCondition (geniCodeLogic (tmp, operandFromLit (0), '<', 0), 0, label);
2313 ADDTOCHAIN (ic);
2315 geniCodeAssign (tmp, geniCodeAdd (tmp, operandFromLit ((1 << p2) - 1), 0, 0), 0, 0);
2316 geniCodeLabel (label);
2317 return (geniCodeCast (resType, geniCodeRightShift (tmp, operandFromLit (p2)), TRUE));
2320 else
2322 ic = newiCode ('/', left, right); /* normal division */
2323 /* if the size left or right > 1 then support routine */
2324 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2325 ic->supportRtn = 1;
2327 IC_RESULT (ic) = newiTempOperand (resType, 0);
2329 ADDTOCHAIN (ic);
2330 return IC_RESULT (ic);
2333 /*-----------------------------------------------------------------*/
2334 /* geniCodeModulus - gen intermediate code for modulus */
2335 /*-----------------------------------------------------------------*/
2336 static operand *
2337 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2339 iCode *ic;
2340 sym_link *resType;
2341 LRTYPE;
2343 /* if they are both literal then we know the result */
2344 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2345 return operandFromValue (valMod (OP_VALUE (left), OP_VALUE (right), true), false);
2347 resType = usualBinaryConversions (&left, &right, resultType, '%');
2349 /* now they are the same size */
2350 ic = newiCode ('%', left, right);
2352 /* if the size left or right > 1 then support routine */
2353 if (getSize (ltype) > 1 || getSize (rtype) > 1)
2354 ic->supportRtn = 1;
2355 IC_RESULT (ic) = newiTempOperand (resType, 0);
2357 ADDTOCHAIN (ic);
2358 return IC_RESULT (ic);
2361 /*-----------------------------------------------------------------*/
2362 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2363 /*-----------------------------------------------------------------*/
2364 operand *
2365 geniCodePtrPtrSubtract (operand * left, operand * right)
2367 iCode *ic;
2368 operand *result;
2369 LRTYPE;
2371 /* if they are both literals then */
2372 if (IS_LITERAL (letype) && IS_LITERAL (retype))
2374 result = operandFromValue (valMinus (OP_VALUE (left), OP_VALUE (right), true), true);
2375 goto subtractExit;
2378 ic = newiCode ('-', left, right);
2380 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2381 ADDTOCHAIN (ic);
2383 subtractExit:
2384 if (IS_VOID (ltype->next) || IS_VOID (rtype->next))
2386 return result;
2389 return geniCodeDivision (result, operandFromLit (getSize (ltype->next)), FALSE, true);
2392 /*-----------------------------------------------------------------*/
2393 /* geniCodeSubtract - generates code for subtraction */
2394 /*-----------------------------------------------------------------*/
2395 static operand *
2396 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2398 iCode *ic;
2399 int isarray = 0;
2400 sym_link *resType;
2401 LRTYPE;
2403 /* if they are both pointers then */
2404 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) && (IS_PTR (rtype) || IS_ARRAY (rtype)))
2405 return geniCodePtrPtrSubtract (left, right);
2407 /* if they are both literal then we know the result */
2408 if (IS_LITERAL (letype) && IS_LITERAL (retype) && left->isLiteral && right->isLiteral)
2409 return operandFromValue (valMinus (OP_VALUE (left), OP_VALUE (right), true), false);
2411 /* if left is an array or pointer */
2412 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2414 isarray = left->isaddr;
2415 right = geniCodeMultiply (right,
2416 operandFromLit (getSize (ltype->next)),
2417 (getArraySizePtr (left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR);
2418 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2420 else
2421 { /* make them the same size */
2422 resType = usualBinaryConversions (&left, &right, resultType, '-');
2425 ic = newiCode ('-', left, right);
2427 IC_RESULT (ic) = newiTempOperand (resType, 1);
2428 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2430 /* if left or right is a float */
2431 if (IS_FLOAT (ltype) || IS_FLOAT (rtype) || IS_FIXED (ltype) || IS_FIXED (rtype))
2432 ic->supportRtn = 1;
2434 ADDTOCHAIN (ic);
2435 return IC_RESULT (ic);
2438 /*-----------------------------------------------------------------*/
2439 /* geniCodeAdd - generates iCode for addition */
2440 /*-----------------------------------------------------------------*/
2441 static operand *
2442 geniCodeAdd (operand *left, operand *right, RESULT_TYPE resultType, int lvl)
2444 iCode *ic;
2445 sym_link *resType;
2446 unsigned int nBytes;
2447 operand *size;
2448 int isarray = 0;
2449 bool indexUnsigned;
2450 LRTYPE;
2452 /* if the right side is LITERAL zero */
2453 /* return the left side */
2454 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2455 return left;
2457 /* if left is literal zero return right */
2458 if (!IS_PTR (ltype) && IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2459 return right;
2461 /* if left is a pointer then size */
2462 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2464 unsigned int ptrSize;
2465 isarray = left->isaddr;
2466 nBytes = getSize (ltype->next);
2467 ptrSize = getArraySizePtr (left); // works for both arrays and pointers
2469 if (nBytes == 0 && !IS_VOID (ltype->next))
2470 werror (E_UNKNOWN_SIZE, IS_SYMOP (left) ? OP_SYMBOL (left)->name : "<no name>");
2471 // there is no need to multiply with 1
2472 if (nBytes != 1)
2474 size = operandFromLit (nBytes);
2475 SPEC_USIGN (getSpec (operandType (size))) = 1;
2476 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2477 if (!indexUnsigned && ptrSize > INTSIZE)
2479 SPEC_LONG (getSpec (operandType (size))) = 1;
2480 SPEC_CVAL (getSpec (operandType (size))).v_ulong = nBytes;
2482 right = geniCodeMultiply (right, size, (ptrSize >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR);
2483 /* Even if right is a 'unsigned char',
2484 the result will be a 'signed int' due to the promotion rules.
2485 It doesn't make sense when accessing arrays, so let's fix it here: */
2486 if (indexUnsigned)
2487 SPEC_USIGN (getSpec (operandType (right))) = 1;
2490 if (ptrSize > getSize (rtype) && !IS_UNSIGNED (retype))
2492 sym_link *type = 0;
2494 switch(ptrSize)
2496 case 2:
2497 type = newIntLink();
2498 break;
2499 case 3:
2500 case 4:
2501 type = newLongLink();
2502 break;
2503 default:
2504 wassert(0);
2506 right = geniCodeCast (type, right, TRUE);
2509 resType = copyLinkChain (ltype);
2511 else
2512 { // make them the same size
2513 resType = usualBinaryConversions (&left, &right, resultType, '+');
2516 /* if they are both literals then we know */
2517 if (IS_LITERAL (letype) && IS_LITERAL (retype) && left->isLiteral && right->isLiteral)
2519 value *scaledRight = valFromType (rtype);
2520 if (IS_PTR (ltype))
2521 scaledRight = valMult (scaledRight, valueFromLit (getSize (ltype->next)), true);
2522 return operandFromValue (valPlus (valFromType (ltype), scaledRight, true), false);
2525 ic = newiCode ('+', left, right);
2527 IC_RESULT (ic) = newiTempOperand (resType, 1);
2528 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2530 /* if left or right is a float then support routine */
2531 if (IS_FLOAT (ltype) || IS_FLOAT (rtype) || IS_FIXED (ltype) || IS_FIXED (rtype))
2532 ic->supportRtn = 1;
2534 ADDTOCHAIN (ic);
2536 return IC_RESULT (ic);
2539 /*-----------------------------------------------------------------*/
2540 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2541 /*-----------------------------------------------------------------*/
2542 sym_link *
2543 aggrToPtr (sym_link * type, bool force)
2545 sym_link *etype;
2546 sym_link *ptype;
2548 if (IS_PTR (type) && !force)
2549 return type;
2551 etype = getSpec (type);
2552 ptype = newLink (DECLARATOR);
2554 ptype->next = type;
2556 /* set the pointer depending on the storage class */
2557 DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2558 return ptype;
2561 /*------------------------------------------------------------------*/
2562 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2563 /*------------------------------------------------------------------*/
2565 aggrToPtrDclType (sym_link * type, bool force)
2567 if (IS_PTR (type) && !force)
2568 return DCL_TYPE (type);
2570 /* return the pointer depending on the storage class */
2571 return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2574 /*-----------------------------------------------------------------*/
2575 /* geniCodeArray2Ptr - array to pointer */
2576 /*-----------------------------------------------------------------*/
2577 static operand *
2578 geniCodeArray2Ptr (operand * op)
2580 sym_link *optype = operandType (op);
2581 sym_link *opetype = getSpec (optype);
2583 /* set the pointer depending on the storage class */
2584 DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2585 /* now remove the storage class from this itemp */
2586 SPEC_SCLS (opetype) = S_FIXED;
2587 SPEC_OCLS (opetype) = NULL;
2589 op->isaddr = 0;
2590 return op;
2594 /*-----------------------------------------------------------------*/
2595 /* geniCodeArray - array access */
2596 /*-----------------------------------------------------------------*/
2597 static operand *
2598 geniCodeArray (operand * left, operand * right, int lvl, bool noderef)
2600 iCode *ic;
2601 operand *size;
2602 sym_link *ltype = operandType (left);
2603 bool indexUnsigned;
2604 RESULT_TYPE resultType;
2606 resultType = (getArraySizePtr (left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
2607 if (DCL_ELEM (ltype))
2609 if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
2610 resultType = RESULT_TYPE_CHAR;
2613 if (IS_PTR (ltype))
2615 if (IS_PTR (ltype->next) && left->isaddr)
2617 left = geniCodeRValue (left, FALSE);
2620 if (noderef)
2621 return geniCodeAdd (left, right, resultType, lvl);
2623 return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl), lvl);
2625 size = operandFromLit (getSize (ltype->next));
2626 SPEC_USIGN (getSpec (operandType (size))) = 1;
2627 indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2628 right = geniCodeMultiply (right, size, resultType);
2629 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2630 It doesn't make sense when accessing arrays, so let's fix it here: */
2631 if (indexUnsigned)
2632 SPEC_USIGN (getSpec (operandType (right))) = 1;
2633 /* we can check for limits here */
2634 /* already done in SDCCast.c
2635 if (isOperandLiteral (right) &&
2636 IS_ARRAY (ltype) &&
2637 DCL_ELEM (ltype) &&
2638 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2640 werror (W_IDX_OUT_OF_BOUNDS,
2641 (int) operandLitValue (right) / getSize (ltype->next),
2642 DCL_ELEM (ltype));
2646 ic = newiCode ('+', left, right);
2648 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) && !IS_AGGREGATE (ltype->next) && !IS_PTR (ltype->next)) ||
2649 (IS_ARRAY (ltype) && IS_FUNCPTR (ltype->next))) ? ltype : ltype->next, 0);
2651 if (!IS_AGGREGATE (ltype->next))
2653 IC_RESULT (ic)->isaddr = 1;
2654 IC_RESULT (ic)->aggr2ptr = 1;
2656 ADDTOCHAIN (ic);
2658 return IC_RESULT (ic);
2661 /*-----------------------------------------------------------------*/
2662 /* geniCodeStruct - generates intermediate code for structures */
2663 /*-----------------------------------------------------------------*/
2664 operand *
2665 geniCodeStruct (operand * left, operand * right, bool islval)
2667 iCode *ic;
2668 sym_link *type = operandType (left);
2669 sym_link *etype = getSpec (type);
2670 sym_link *rtype, *retype;
2671 symbol *element = getStructElement (SPEC_STRUCT (etype), OP_SYMBOL (right));
2673 wassert (IS_SYMOP (right));
2675 wassert (IS_STRUCT (type) || ((IS_PTR (type) || IS_ARRAY (type)) && IS_STRUCT (type->next)));
2677 /* add the offset */
2678 ic = newiCode ('+', left, operandFromLit (element->offset));
2680 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2682 /* preserve the storage & output class of the struct */
2683 /* as well as the volatile attribute */
2684 rtype = operandType (IC_RESULT (ic));
2685 retype = getSpec (rtype);
2686 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2687 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2689 if (IS_PTR (element->type))
2691 DCL_PTR_CONST (rtype) |= DCL_PTR_CONST (element->type);
2692 DCL_PTR_VOLATILE (rtype) |= DCL_PTR_VOLATILE (element->type);
2693 DCL_PTR_RESTRICT (rtype) |= DCL_PTR_RESTRICT (element->type);
2694 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2696 else
2698 SPEC_CONST (retype) |= SPEC_CONST (etype);
2699 /*Do not preserve volatile */
2700 SPEC_RESTRICT (retype) |= SPEC_RESTRICT (etype);
2703 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2705 ADDTOCHAIN (ic);
2706 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2709 /*-----------------------------------------------------------------*/
2710 /* geniCodePostInc - generate int code for Post increment */
2711 /*-----------------------------------------------------------------*/
2712 operand *
2713 geniCodePostInc (operand * op)
2715 iCode *ic;
2716 operand *rOp;
2717 sym_link *optype = operandType (op);
2718 operand *result;
2719 operand *rv = (IS_ITEMP (op) ? geniCodeRValue (op, (!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE) : op);
2720 sym_link *rvtype = operandType (rv);
2721 int size = 0;
2722 operand *srcOp = rv;
2724 /* if this is not an address we have trouble */
2725 if (!op->isaddr)
2727 werror (E_LVALUE_REQUIRED, "++");
2728 return op;
2731 rOp = newiTempOperand (rvtype, 0);
2732 OP_SYMBOL (rOp)->noSpilLoc = 1;
2734 if (IS_ITEMP (rv))
2735 OP_SYMBOL (rv)->noSpilLoc = 1;
2737 geniCodeAssign (rOp, rv, 0, 0);
2739 /* If rv is volatile, we can only read it once, and we've just */
2740 /* done that, so use the copy in rOp instead to avoid reading */
2741 /* it again. */
2742 if (isOperandVolatile (rv, FALSE))
2743 srcOp = rOp;
2745 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2746 if (size == 0)
2747 werror (W_SIZEOF_VOID);
2748 if (IS_FLOAT (rvtype))
2749 ic = newiCode ('+', srcOp, operandFromValue (constFloatVal ("1.0"), false));
2750 else if (IS_FIXED16X16 (rvtype))
2751 ic = newiCode ('+', srcOp, operandFromValue (constFixed16x16Val ("1.0"), false));
2752 else if (IS_BOOL (rvtype))
2753 ic = newiCode ('=', NULL, operandFromLit (1));
2754 else
2755 ic = newiCode ('+', srcOp, operandFromLit (size));
2757 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2758 ADDTOCHAIN (ic);
2760 geniCodeAssign (op, result, 0, 0);
2762 return rOp;
2766 /*-----------------------------------------------------------------*/
2767 /* geniCodePreInc - generate code for preIncrement */
2768 /*-----------------------------------------------------------------*/
2769 operand *
2770 geniCodePreInc (operand * op, bool lvalue)
2772 iCode *ic;
2773 sym_link *optype = operandType (op);
2774 operand *rop = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2775 sym_link *roptype = operandType (rop);
2776 operand *result;
2777 int size = 0;
2779 if (!op->isaddr)
2781 werror (E_LVALUE_REQUIRED, "++");
2782 return op;
2785 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2786 if (size == 0)
2787 werror (W_SIZEOF_VOID);
2788 if (IS_FLOAT (roptype))
2789 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0"), false));
2790 else if (IS_FIXED16X16 (roptype))
2791 ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0"), false));
2792 else if (IS_BOOL (roptype))
2793 ic = newiCode ('=', NULL, operandFromLit (1));
2794 else
2795 ic = newiCode ('+', rop, operandFromLit (size));
2796 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2797 ADDTOCHAIN (ic);
2799 (void) geniCodeAssign (op, result, 0, 0);
2800 if (lvalue || (IS_TRUE_SYMOP (op) && !isOperandVolatile (op, FALSE)) || IS_BITVAR (optype))
2801 return op;
2802 else
2803 return result;
2806 /*-----------------------------------------------------------------*/
2807 /* geniCodePostDec - generates code for Post decrement */
2808 /*-----------------------------------------------------------------*/
2809 operand *
2810 geniCodePostDec (operand * op)
2812 iCode *ic;
2813 operand *rOp;
2814 sym_link *optype = operandType (op);
2815 operand *result;
2816 operand *rv = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2817 sym_link *rvtype = operandType (rv);
2818 int size = 0;
2819 operand *srcOp = rv;
2821 /* if this is not an address we have trouble */
2822 if (!op->isaddr)
2824 werror (E_LVALUE_REQUIRED, "--");
2825 return op;
2828 rOp = newiTempOperand (rvtype, 0);
2829 OP_SYMBOL (rOp)->noSpilLoc = 1;
2831 if (IS_ITEMP (rv))
2832 OP_SYMBOL (rv)->noSpilLoc = 1;
2834 geniCodeAssign (rOp, rv, 0, 0);
2836 /* If rv is volatile, we can only read it once, and we've just */
2837 /* done that, so use the copy in rOp instead to avoid reading */
2838 /* it again. */
2839 if (isOperandVolatile (rv, FALSE))
2840 srcOp = rOp;
2842 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2843 if (size == 0)
2844 werror (W_SIZEOF_VOID);
2845 if (IS_FLOAT (rvtype))
2846 ic = newiCode ('-', srcOp, operandFromValue (constFloatVal ("1.0"), false));
2847 else if (IS_FIXED16X16 (rvtype))
2848 ic = newiCode ('-', srcOp, operandFromValue (constFixed16x16Val ("1.0"), false));
2849 else if (IS_BOOL (rvtype))
2850 ic = newiCode ('!', srcOp, 0);
2851 else
2852 ic = newiCode ('-', srcOp, operandFromLit (size));
2854 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2855 ADDTOCHAIN (ic);
2857 geniCodeAssign (op, result, 0, 0);
2859 return rOp;
2863 /*-----------------------------------------------------------------*/
2864 /* geniCodePreDec - generate code for pre decrement */
2865 /*-----------------------------------------------------------------*/
2866 operand *
2867 geniCodePreDec (operand * op, bool lvalue)
2869 iCode *ic;
2870 sym_link *optype = operandType (op);
2871 operand *rop = (IS_ITEMP (op) ? geniCodeRValue (op, ((!op->aggr2ptr && IS_PTR (optype)) ? TRUE : FALSE)) : op);
2872 sym_link *roptype = operandType (rop);
2873 operand *result;
2874 int size = 0;
2876 if (!op->isaddr)
2878 werror (E_LVALUE_REQUIRED, "--");
2879 return op;
2882 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2883 if (size == 0)
2884 werror (W_SIZEOF_VOID);
2885 if (IS_FLOAT (roptype))
2886 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0"), false));
2887 else if (IS_FIXED16X16 (roptype))
2888 ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0"), false));
2889 else if (IS_BOOL (roptype))
2890 ic = newiCode ('!', rop, 0);
2891 else
2892 ic = newiCode ('-', rop, operandFromLit (size));
2893 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2894 ADDTOCHAIN (ic);
2896 (void) geniCodeAssign (op, result, 0, 0);
2897 if (lvalue || (IS_TRUE_SYMOP (op) && !isOperandVolatile (op, FALSE)) || IS_BITVAR (optype))
2898 return op;
2899 else
2900 return result;
2904 /*-----------------------------------------------------------------*/
2905 /* geniCodeBitwise - gen int code for bitWise operators */
2906 /*-----------------------------------------------------------------*/
2907 operand *
2908 geniCodeBitwise (operand * left, operand * right, int oper, sym_link * resType)
2910 iCode *ic;
2912 /* Signedness doesn't matter for bit ops, so omit */
2913 /* possible cast if that is the only difference */
2914 if (compareType (resType, operandType (left), false) != -2)
2915 left = geniCodeCast (resType, left, TRUE);
2916 if (compareType (resType, operandType (right), false) != -2)
2917 right = geniCodeCast (resType, right, TRUE);
2919 ic = newiCode (oper, left, right);
2920 IC_RESULT (ic) = newiTempOperand (resType, 0);
2922 ADDTOCHAIN (ic);
2923 return IC_RESULT (ic);
2926 /*-----------------------------------------------------------------*/
2927 /* geniCodeAddressOf - gens icode for '&' address of operator */
2928 /*-----------------------------------------------------------------*/
2929 operand *
2930 geniCodeAddressOf (operand * op)
2932 iCode *ic;
2933 sym_link *p;
2934 sym_link *optype = operandType (op);
2935 sym_link *opetype = getSpec (optype);
2937 if (IS_ITEMP (op) && IS_PTR (optype))
2939 op = operandFromOperand (op);
2940 op->isaddr = 0;
2941 return op;
2944 /* lvalue check already done in decorateType */
2945 /* this must be a lvalue */
2946 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2947 /* werror (E_LVALUE_REQUIRED,"&"); */
2948 /* return op; */
2949 /* } */
2951 p = newLink (DECLARATOR);
2953 /* set the pointer depending on the storage class */
2954 DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2956 p->next = copyLinkChain (optype);
2958 /* if already a temp */
2959 if (IS_ITEMP (op))
2961 setOperandType (op, p);
2962 op->isaddr = 0;
2963 return op;
2966 /* otherwise make this of the type coming in */
2967 ic = newiCode (ADDRESS_OF, op, operandFromLit (0));
2968 IC_RESULT (ic) = newiTempOperand (p, 1);
2969 IC_RESULT (ic)->isaddr = 0;
2970 ADDTOCHAIN (ic);
2971 return IC_RESULT (ic);
2974 /*-----------------------------------------------------------------*/
2975 /* setOClass - sets the output class depending on the pointer type */
2976 /*-----------------------------------------------------------------*/
2977 void
2978 setOClass (sym_link * ptr, sym_link * spec)
2980 switch (DCL_TYPE (ptr))
2982 case POINTER:
2983 SPEC_OCLS (spec) = data;
2984 break;
2986 case GPOINTER:
2987 SPEC_OCLS (spec) = generic;
2988 break;
2990 case FPOINTER:
2991 SPEC_OCLS (spec) = xdata;
2992 break;
2994 case CPOINTER:
2995 SPEC_OCLS (spec) = code;
2996 break;
2998 case IPOINTER:
2999 SPEC_OCLS (spec) = idata;
3000 break;
3002 case PPOINTER:
3003 SPEC_OCLS (spec) = xstack;
3004 break;
3006 case EEPPOINTER:
3007 SPEC_OCLS (spec) = eeprom;
3008 break;
3010 default:
3011 break;
3015 /*-----------------------------------------------------------------*/
3016 /* geniCodeDerefPtr - dereference pointer with '*' */
3017 /*-----------------------------------------------------------------*/
3018 operand *
3019 geniCodeDerefPtr (operand *op, int lvl)
3021 sym_link *rtype, *retype;
3022 sym_link *optype = operandType (op);
3024 // if this is an array then array access
3025 if (IS_ARRAY (optype))
3027 // don't worry, this will be optimized out later
3028 return geniCodeArray (op, operandFromLit (0), lvl, false);
3031 // just in case someone screws up
3032 wassert (IS_PTR (optype));
3034 if (IS_TRUE_SYMOP (op))
3036 op->isaddr = 1;
3037 op = geniCodeRValue (op, TRUE);
3039 else if (IS_OP_LITERAL (op))
3041 /* To avoid problems converting a dereferenced literal pointer */
3042 /* back and forth between lvalue and rvalue formats, replace */
3043 /* the literal pointer with an iTemp and assign the literal */
3044 /* value to the iTemp. */
3045 iCode *ic;
3046 operand *iop = newiTempOperand (optype, 0);
3047 SPEC_SCLS (OP_SYM_ETYPE (iop)) = S_AUTO; /* remove S_LITERAL */
3048 iop->isaddr = 0; /* assign to the iTemp itself */
3049 ic = newiCode ('=', NULL, op);
3050 IC_RESULT (ic) = iop;
3051 ADDTOCHAIN (ic);
3052 op = operandFromOperand (iop); /* now use the iTemp as operand */
3053 optype = operandType (op);
3056 /* now get rid of the pointer part */
3057 if (isLvaluereq (lvl) && IS_ITEMP (op))
3059 retype = getSpec (rtype = copyLinkChain (optype));
3061 else
3063 retype = getSpec (rtype = copyLinkChain (optype->next));
3064 /* outputclass needs 2b updated */
3065 setOClass (optype, retype);
3068 op->isGptr = IS_GENPTR (optype);
3070 op->isaddr = (IS_PTR (rtype) ||
3071 IS_STRUCT (rtype) || IS_INT (rtype) || IS_BITINT (rtype) || IS_BOOL (rtype) || IS_CHAR (rtype) || IS_FLOAT (rtype) || IS_FIXED (rtype));
3073 if (!isLvaluereq (lvl))
3074 op = geniCodeRValue (op, TRUE);
3076 if (IS_DECL (rtype))
3078 DCL_PTR_ADDRSPACE (rtype) = 0;
3079 DCL_PTR_VOLATILE (rtype) = 0;
3081 else
3083 SPEC_ADDRSPACE (rtype) = 0;
3084 SPEC_VOLATILE (rtype) = 0;
3086 setOperandType (op, rtype);
3088 return op;
3091 /*-----------------------------------------------------------------*/
3092 /* geniCodeUnaryMinus - does a unary minus of the operand */
3093 /*-----------------------------------------------------------------*/
3094 operand *
3095 geniCodeUnaryMinus (operand * op)
3097 iCode *ic;
3098 sym_link *optype = operandType (op);
3100 if (IS_LITERAL (optype))
3101 return operandFromLit (-floatFromVal (OP_VALUE (op)));
3103 ic = newiCode (UNARYMINUS, op, NULL);
3104 IC_RESULT (ic) = newiTempOperand (optype, 0);
3105 ADDTOCHAIN (ic);
3106 return IC_RESULT (ic);
3109 /*-----------------------------------------------------------------*/
3110 /* geniCodeLeftShift - gen i code for left shift */
3111 /*-----------------------------------------------------------------*/
3112 operand *
3113 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
3115 iCode *ic;
3116 sym_link *resType;
3118 resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
3119 ic = newiCode(LEFT_OP, left, right);
3120 IC_RESULT (ic) = newiTempOperand (resType, 0);
3121 ADDTOCHAIN (ic);
3122 return IC_RESULT (ic);
3125 /*-----------------------------------------------------------------*/
3126 /* geniCodeRightShift - gen i code for right shift */
3127 /*-----------------------------------------------------------------*/
3128 operand *
3129 geniCodeRightShift (operand * left, operand * right)
3131 iCode *ic;
3133 ic = newiCode (RIGHT_OP, left, right);
3134 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3135 ADDTOCHAIN (ic);
3136 return IC_RESULT (ic);
3139 /*-----------------------------------------------------------------*/
3140 /* geniCodeLogic- logic code */
3141 /*-----------------------------------------------------------------*/
3142 static operand *
3143 geniCodeLogic (operand * left, operand * right, int op, ast * tree)
3145 iCode *ic;
3146 sym_link *ctype, *ttype;
3147 sym_link *rtype = operandType (right);
3148 sym_link *ltype = operandType (left);
3150 /* left is integral type and right is literal then
3151 check if the literal value is within bounds */
3152 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
3154 CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
3155 switch (ccr_result)
3157 case CCR_ALWAYS_TRUE:
3158 case CCR_ALWAYS_FALSE:
3159 werror (W_COMP_RANGE, "true resp. false");
3160 return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
3161 default:
3162 break;
3166 /* Avoid expensive comparisons when the type of the constant is bigger than the type of the non-const operand */
3167 if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype) && getSize (ltype) < getSize (rtype))
3168 right->svt.valOperand = valCastLiteral (ltype, operandLitValue (right), operandLitValueUll (right));
3169 if (IS_INTEGRAL (rtype) && IS_LITERAL (ltype) && getSize (rtype) < getSize (ltype))
3170 left->svt.valOperand = valCastLiteral (rtype, operandLitValue (left), operandLitValueUll (left));
3172 /* if one operand is a pointer and the other is a literal generic void pointer,
3173 change the type of the literal generic void pointer to match the other pointer */
3174 if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left) && IS_PTR (rtype) && !IS_GENPTR (rtype))
3176 /* find left's definition */
3177 ic = iCodeChain;
3178 while (ic)
3180 if (((ic->op == CAST) || (ic->op == '=')) && isOperandEqual (left, IC_RESULT (ic)))
3181 break;
3182 else
3183 ic = ic->next;
3185 /* if casting literal to generic pointer, then cast to rtype instead */
3186 if (ic && (ic->op == CAST) && isOperandLiteral (IC_RIGHT (ic)))
3188 left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic)),operandLitValueUll (IC_RIGHT (ic))), false);
3189 ltype = operandType (left);
3192 if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right) && IS_PTR (ltype) && !IS_GENPTR (ltype))
3194 /* find right's definition */
3195 ic = iCodeChain;
3196 while (ic)
3198 if (((ic->op == CAST) || (ic->op == '=')) && isOperandEqual (right, IC_RESULT (ic)))
3199 break;
3200 else
3201 ic = ic->next;
3203 /* if casting literal to generic pointer, then cast to rtype instead */
3204 if (ic && (ic->op == CAST) && isOperandLiteral (IC_RIGHT (ic)))
3206 right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic)), operandLitValueUll (IC_RIGHT (ic))), false);
3207 rtype = operandType (right);
3211 ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_BOOL, op);
3213 ic = newiCode (op, left, right);
3214 /* store 0 or 1 in result */
3215 ttype = (tree && IS_BOOLEAN (tree->ftype)) ? newBoolLink () : newCharLink ();
3216 IC_RESULT (ic) = newiTempOperand (ttype, 1);
3218 /* if comparing float
3219 and not a '==' || '!=' || '&&' || '||' (these
3220 will be inlined */
3221 if (IS_FLOAT (ctype) && op != EQ_OP && op != NE_OP && op != AND_OP && op != OR_OP)
3222 ic->supportRtn = 1;
3224 /* if comparing a fixed type use support functions */
3225 if (IS_FIXED (ctype))
3226 ic->supportRtn = 1;
3228 ADDTOCHAIN (ic);
3229 return IC_RESULT (ic);
3232 /*-----------------------------------------------------------------*/
3233 /* geniCodeLogicAndOr - && || operations */
3234 /*-----------------------------------------------------------------*/
3235 static operand *
3236 geniCodeLogicAndOr (ast * tree, int lvl)
3238 iCode *ic;
3239 sym_link *type;
3240 symbol *falseLabel = newiTempLabel (NULL);
3241 symbol *trueLabel = newiTempLabel (NULL);
3242 symbol *exitLabel = newiTempLabel (NULL);
3243 operand *op, *result, *condition;
3245 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3246 They can be reenabled by executing the following block. If you find
3247 a decent optimization you could start right here:
3249 #if 0
3250 if (0)
3252 operand *leftOp, *rightOp;
3254 leftOp = geniCodeRValue (ast2iCode (tree->left, lvl + 1), FALSE);
3255 rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3257 return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3259 #endif
3261 /* generate two IFX for the '&&' or '||' op */
3263 /* evaluate left operand */
3264 condition = ast2iCode (tree->left, lvl + 1);
3265 op = geniCodeRValue (condition, FALSE);
3267 /* test left operand */
3268 if (tree->opval.op == AND_OP)
3269 ic = newiCodeCondition (op, NULL, falseLabel);
3270 else /* OR_OP */
3271 ic = newiCodeCondition (op, trueLabel, NULL);
3272 ADDTOCHAIN (ic);
3274 /* evaluate right operand */
3275 condition = ast2iCode (tree->right, lvl + 1);
3276 op = geniCodeRValue (condition, FALSE);
3278 /* test right operand */
3279 ic = newiCodeCondition (op, trueLabel, NULL);
3280 ADDTOCHAIN (ic);
3282 /* store 0 or 1 in result */
3283 type = (IS_BOOLEAN (tree->ftype)) ? newBoolLink () : newCharLink ();
3284 result = newiTempOperand (type, 1);
3286 geniCodeLabel (falseLabel);
3287 geniCodeAssign (result, operandFromLit (0), 0, 0);
3288 /* generate an unconditional goto */
3289 geniCodeGoto (exitLabel);
3291 geniCodeLabel (trueLabel);
3292 geniCodeAssign (result, operandFromLit (1), 0, 0);
3294 geniCodeLabel (exitLabel);
3296 return result;
3299 /*-----------------------------------------------------------------*/
3300 /* geniCodeUnary - for a generic unary operation */
3301 /*-----------------------------------------------------------------*/
3302 operand *
3303 geniCodeUnary (operand * op, int oper, sym_link * resType)
3305 iCode *ic = newiCode (oper, op, NULL);
3307 IC_RESULT (ic) = newiTempOperand (resType, 0);
3308 ADDTOCHAIN (ic);
3309 return IC_RESULT (ic);
3312 /*-----------------------------------------------------------------*/
3313 /* geniCodeBinary - for a generic binary operation */
3314 /*-----------------------------------------------------------------*/
3315 operand *
3316 geniCodeBinary (operand * left, operand * right, int oper, sym_link * resType)
3318 iCode *ic = newiCode (oper, left, right);
3320 IC_RESULT (ic) = newiTempOperand (resType, 0);
3321 ADDTOCHAIN (ic);
3322 return IC_RESULT (ic);
3325 /*-----------------------------------------------------------------*/
3326 /* geniCodeConditional - geniCode for '?' ':' operation */
3327 /*-----------------------------------------------------------------*/
3328 operand *
3329 geniCodeConditional (ast * tree, int lvl)
3331 iCode *ic;
3332 symbol *falseLabel = newiTempLabel (NULL);
3333 symbol *exitLabel = newiTempLabel (NULL);
3334 ast *astTrue = tree->right->left;
3335 ast *astFalse = tree->right->right;
3336 operand *cond = ast2iCode (tree->left, lvl + 1);
3337 operand *result = newiTempOperand (tree->ftype, 0);
3338 operand *opTrue, *opFalse;
3340 ic = newiCodeCondition (geniCodeRValue (cond, FALSE), NULL, falseLabel);
3341 ADDTOCHAIN (ic);
3343 opTrue = ast2iCode (astTrue, lvl + 1);
3345 /* move the value to the new operand */
3346 geniCodeAssign (result, geniCodeRValue (opTrue, FALSE), 0, 0);
3348 /* generate an unconditional goto */
3349 geniCodeGoto (exitLabel);
3351 /* now for the right side */
3352 geniCodeLabel (falseLabel);
3354 opFalse = ast2iCode (astFalse, lvl + 1);
3355 geniCodeAssign (result, geniCodeRValue (opFalse, FALSE), 0, 0);
3357 /* create the exit label */
3358 geniCodeLabel (exitLabel);
3360 return result;
3363 /*-----------------------------------------------------------------*/
3364 /* checkTypes - check types for assignment */
3365 /*-----------------------------------------------------------------*/
3366 static operand *
3367 checkTypes (operand * left, operand * right)
3369 sym_link *ltype = operandType (left);
3370 sym_link *rtype = operandType (right);
3371 bool always_cast = FALSE;
3373 /* if the left & right type don't exactly match */
3374 /* if pointer set then make sure the check is
3375 done with the type & not the pointer */
3376 /* then cast rights type to left */
3378 /* first check the type for pointer assignment */
3379 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) && compareType (ltype, rtype, false) <= 0)
3381 if (left->aggr2ptr)
3383 always_cast = TRUE;
3385 else
3387 ltype = ltype->next;
3391 /* left is integral type and right is literal then
3392 check if the literal value is within bounds */
3393 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
3394 checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL)
3396 werror (W_LIT_OVERFLOW);
3399 if (always_cast || compareType (ltype, rtype, false) == -1)
3401 if (IS_VOLATILE (ltype)) // Don't propagate volatile to right side - we don't want volatile iTemps.
3403 ltype = copyLinkChain (ltype);
3404 if (IS_DECL(ltype))
3405 DCL_PTR_VOLATILE (ltype) = 0;
3406 else
3407 SPEC_VOLATILE (ltype) = 0;
3409 right = geniCodeCast (ltype, right, TRUE);
3411 checkPtrQualifiers (ltype, rtype, !right->isConstElimnated);
3412 return right;
3415 /*-----------------------------------------------------------------*/
3416 /* geniCodeAssign - generate code for assignment */
3417 /*-----------------------------------------------------------------*/
3418 operand *
3419 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3421 iCode *ic;
3422 sym_link *ltype;
3424 if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3426 werror (E_LVALUE_REQUIRED, "assignment");
3427 return left;
3430 right = checkTypes (left, right);
3432 /* If left is a true symbol & ! volatile
3433 create an assignment to temporary for
3434 the right & then assign this temporary
3435 to the symbol. This is SSA (static single
3436 assignment). Isn't it simple and folks have
3437 published mountains of paper on it */
3438 if (IS_TRUE_SYMOP (left) && !isOperandVolatile (left, FALSE) && isOperandGlobal (left))
3440 symbol *sym = NULL;
3441 operand *newRight;
3442 sym_link *ltype = operandType (left);
3444 if (IS_TRUE_SYMOP (right))
3445 sym = OP_SYMBOL (right);
3446 ic = newiCode ('=', NULL, right);
3447 IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
3448 /* avoid double fetch from volatile right, see bug 1369874 */
3449 if (!isOperandVolatile (right, FALSE))
3450 SPIL_LOC (newRight) = sym;
3451 right = newRight;
3452 ADDTOCHAIN (ic);
3455 ic = newiCode ('=', NULL, right);
3456 IC_RESULT (ic) = left;
3457 ADDTOCHAIN (ic);
3459 /* if left isgptr flag is set then support
3460 routine will be required */
3461 if (left->isGptr)
3462 ic->supportRtn = 1;
3464 ic->nosupdate = nosupdate;
3465 /* left could be a pointer assignment,
3466 return the properly casted right instead */
3467 ltype = operandType (left);
3468 if ((IS_PTR (ltype) && IS_BITVAR (ltype->next)) || IS_BITVAR (ltype))
3469 return left;
3470 else
3471 return right;
3474 /*-----------------------------------------------------------------*/
3475 /* geniCodeDummyRead - generate code for dummy read */
3476 /*-----------------------------------------------------------------*/
3477 static void
3478 geniCodeDummyRead (operand * op)
3480 iCode *ic;
3481 sym_link *type = operandType (op);
3483 if (!IS_VOLATILE (type))
3484 return;
3486 ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3487 ADDTOCHAIN (ic);
3489 ic->nosupdate = 1;
3492 /*-----------------------------------------------------------------*/
3493 /* geniCodeSEParms - generate code for side effecting fcalls */
3494 /*-----------------------------------------------------------------*/
3495 static void
3496 geniCodeSEParms (ast *parms, int lvl)
3498 if (!parms)
3499 return;
3501 if (IS_AST_PARAM (parms))
3503 geniCodeSEParms (parms->left, lvl);
3504 geniCodeSEParms (parms->right, lvl);
3505 return;
3508 /* hack don't like this but too lazy to think of
3509 something better */
3510 if (IS_ADDRESS_OF_OP (parms))
3511 parms->left->lvalue = 1;
3513 if (IS_CAST_OP (parms) && IS_PTR (parms->ftype) && IS_ADDRESS_OF_OP (parms->right))
3514 parms->right->left->lvalue = 1;
3516 if (parms->type == EX_OP && parms->opval.op == '[' && IS_STRUCT (parms->ftype)) // Do not dereference pointer to struct.
3517 parms->opval.op = '+';
3519 parms->opval.oprnd = geniCodeRValue (ast2iCode (parms, lvl + 1), FALSE);
3520 parms->type = EX_OPERAND;
3521 AST_ARGREG (parms) = parms->etype ? SPEC_ARGREG (parms->etype) : SPEC_ARGREG (parms->ftype);
3524 /*-----------------------------------------------------------------*/
3525 /* geniCodeParms - generates parameters */
3526 /*-----------------------------------------------------------------*/
3527 value *
3528 geniCodeParms (ast * parms, value * argVals, int *iArg, int *stack, sym_link * ftype, int lvl, iCode *iic_start)
3530 iCode *ic;
3531 iCode *castic_start = 0;
3532 iCode *castic_end = 0;
3533 operand *pval;
3535 if (!parms)
3536 return argVals;
3538 if (!iic_start)
3539 iic_start = iCodeChainEnd;
3541 /* if this is a param node then do the left & right */
3542 if (parms->type == EX_OP && parms->opval.op == PARAM)
3544 argVals = geniCodeParms (parms->left, argVals, iArg, stack, ftype, lvl, iic_start);
3545 argVals = geniCodeParms (parms->right, argVals, iArg, stack, ftype, lvl, iic_start);
3546 return argVals;
3549 // Get the parameter value. All the real work for this was done in geniCodeSEParms already.
3550 wassert (parms->type == EX_OPERAND);
3551 pval = parms->opval.oprnd;
3553 /* if register parm then make it a send */
3554 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS (ftype)) || IFFUNC_ISBUILTIN (ftype))
3556 pval = checkTypes (operandFromValue (argVals, true), pval);
3557 ic = newiCode (SEND, pval, NULL);
3558 ic->argreg = SPEC_ARGREG (parms->etype);
3559 ic->builtinSEND = FUNC_ISBUILTIN (ftype);
3560 ADDTOCHAIN (ic);
3562 else
3564 bool is_structparm = IS_STRUCT (parms->ftype); // struct parameter handling is hackish.
3565 if (is_structparm)
3567 sym_link *ptr = newLink (DECLARATOR);
3568 DCL_TYPE (ptr) = PTR_TYPE (SPEC_OCLS (getSpec (operandType (pval))));
3569 ptr->next = copyLinkChain (parms->ftype);
3570 if (IS_PTR (operandType (pval)))
3572 pval = geniCodeCast (ptr, pval, true);
3574 setOperandType (pval, ptr);
3576 // now decide whether to push or assign
3577 if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3579 if (is_structparm) // Passing the parameter requires a memcpy.
3581 iCode *dstic, *srcic, *nic, *cic, *iic_end;
3582 // Keep this one in mind in so we can move it later.
3583 if (iic_start != iCodeChainEnd)
3584 castic_start = iCodeChainEnd;
3585 operand *dstop = geniCodeCast (FUNC_ARGS(builtin_memcpy->type)->type, operandFromValue (argVals, true), false);
3586 castic_end = iCodeChainEnd;
3587 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->etype))
3589 dstic = newiCode (SEND, dstop, 0);
3590 dstic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->etype);
3592 else
3594 dstic = newiCode ('=', 0, dstop);
3595 IC_RESULT (dstic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type), false);
3597 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->next->etype))
3599 srcic = newiCode (SEND, pval, 0);
3600 srcic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->next->etype);
3602 else
3604 srcic = newiCode ('=', 0, pval);
3605 IC_RESULT (srcic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type)->next, false);
3607 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy->type)->next->next->etype))
3609 nic = newiCode (SEND, operandFromLit (getSize (parms->ftype)), 0);
3610 nic->argreg = SPEC_ARGREG (FUNC_ARGS (builtin_memcpy->type)->next->next->etype);
3612 else
3614 nic = newiCode ('=', 0, operandFromLit (getSize (parms->ftype)));
3615 IC_RESULT (nic) = operandFromValue (FUNC_ARGS(builtin_memcpy->type)->next->next, false);
3617 cic = newiCode (CALL, operandFromSymbol (builtin_memcpy, false), 0);
3618 IC_RESULT (cic) = newiTempOperand (builtin_memcpy->type->next, 0);
3619 // Insert before passing any other parameters - otherwise register parameters to the function will instead up as parameters to the memcpy call.
3620 if (castic_start)
3622 iCode *castic = castic_start->next;
3623 //Cut out cast from where it is.
3624 castic_start->next = castic_end->next;
3625 if (castic_end->next)
3626 castic_end->next->prev = castic_start;
3627 if (castic_end == iCodeChainEnd)
3628 iCodeChainEnd = castic_start;
3629 // Insert it earlier.
3630 iic_end = iic_start->next;
3631 iic_start->next = castic;
3632 castic->prev = iic_start;
3633 castic_end->next = iic_end;
3634 if (iic_end)
3635 iic_end->prev = castic_end;
3637 iic_start = castic_end;
3638 iic_end = iic_start->next;
3639 iic_start->next = dstic;
3640 dstic->prev = iic_start;
3641 dstic->next = srcic;
3642 srcic->prev = dstic;
3643 srcic->next = nic;
3644 nic->prev = srcic;
3645 nic->next = cic;
3646 cic->prev = nic;
3647 cic->next = iic_end;
3648 if (iic_end)
3649 iic_end->prev = cic;
3650 else if (iic_start == iCodeChainEnd)
3651 iCodeChainEnd = cic;
3653 else
3655 // assign
3656 operand *top = operandFromValue (argVals, true);
3657 // clear useDef and other bitVectors
3658 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL (top)->clashes = 0;
3659 geniCodeAssign (top, pval, 1, 0);
3662 else
3664 if (argVals && (*iArg >= 0))
3665 pval = checkTypes (operandFromValue (argVals, false), pval);
3666 // push
3667 if (is_structparm)
3668 ic = newiCode (IPUSH_VALUE_AT_ADDRESS , pval, operandFromLit (0));
3669 else
3670 ic = newiCode (IPUSH, pval, NULL);
3671 ic->parmPush = 1;
3672 // update the stack adjustment
3673 sym_link *parmtype = IS_ARRAY (parms->ftype) ? aggrToPtr (parms->ftype, false) : parms->ftype;
3674 *stack += getSize (parmtype);
3675 if (IFFUNC_ISSMALLC (ftype) && getSize (parmtype) == 1) // SmallC calling convention passes 8-bit parameters as 16-bit values.
3676 (*stack)++;
3677 if (TARGET_PDK_LIKE && getSize (parmtype) % 2) // So does pdk due to stack alignment requirements.
3678 (*stack)++;
3679 ADDTOCHAIN (ic);
3683 if (*iArg >= 0)
3685 assert (argVals != NULL);
3686 argVals = argVals->next;
3688 (*iArg)++;
3689 return argVals;
3692 /*-----------------------------------------------------------------*/
3693 /* geniCodeCall - generates temp code for calling */
3694 /*-----------------------------------------------------------------*/
3695 operand *
3696 geniCodeCall (operand * left, ast * parms, int lvl)
3698 iCode *ic;
3699 sym_link *type, *etype;
3700 sym_link *ftype;
3701 int stack = 0;
3702 int iArg = 0;
3704 if (IS_ARRAY (operandType (left)))
3706 iCode *tic;
3707 sym_link *ttype;
3709 tic = newiCode (GET_VALUE_AT_ADDRESS, left, operandFromLit (0));
3710 ttype = copyLinkChain (operandType (left)->next);
3711 IC_RESULT (tic) = newiTempOperand (ttype, 1);
3712 IC_RESULT (tic)->isaddr = IS_FUNCPTR (ttype) ? 1 : 0;
3713 ADDTOCHAIN (tic);
3714 left = IC_RESULT (tic);
3717 ftype = operandType (left);
3718 if (!IS_FUNC (ftype) && !IS_FUNCPTR (ftype))
3720 werror (E_FUNCTION_EXPECTED);
3721 return operandFromValue (valueFromLit (0), false);
3724 // 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)
3725 if (!IS_FUNCPTR (ftype) && !strcmp(OP_SYMBOL (left)->name, "__builtin_unreachable"))
3726 return 0;
3728 // not allow call a critical function
3729 if (inCriticalPair && FUNC_ISCRITICAL (ftype))
3730 werror (E_INVALID_CRITICAL);
3732 /* take care of parameters with side-effecting
3733 function calls in them, this is required to take care
3734 of overlaying function parameters */
3735 geniCodeSEParms (parms, lvl);
3737 if (IS_FUNCPTR (ftype))
3738 ftype = ftype->next;
3740 /* first the parameters */
3741 if ((options.stackAuto || IFFUNC_ISREENT (ftype)) && !IFFUNC_ISBUILTIN (ftype))
3743 value *argVals;
3744 int nArgs = 0;
3745 ast *parm;
3746 int nParms = 0;
3748 //count expected arguments except varargs
3749 for (argVals = FUNC_ARGS (ftype); argVals; argVals = argVals->next)
3750 nArgs++;
3751 //count actual parameters including varargs
3752 for (parm = parms; parm && parm->type == EX_OP && parm->opval.op == PARAM; parm = parm->right)
3754 if (parm->left)
3755 nParms++;
3757 if (parm)
3758 nParms++;
3759 argVals = FUNC_ARGS (ftype);
3760 iArg = nArgs - nParms;
3762 // reverse the argVals to match the parms
3763 argVals = reverseVal (argVals);
3764 geniCodeParms (parms, argVals, &iArg, &stack, ftype, lvl, 0);
3765 argVals = reverseVal (argVals);
3767 else
3769 geniCodeParms (parms, FUNC_ARGS (ftype), &iArg, &stack, ftype, lvl, 0);
3772 /* now call : if symbol then pcall */
3773 if (IS_OP_POINTER (left) || IS_ITEMP (left))
3775 ic = newiCode (PCALL, left, NULL);
3777 else
3779 ic = newiCode (CALL, left, NULL);
3782 type = copyLinkChain (ftype->next);
3783 etype = getSpec (type);
3784 SPEC_EXTR (etype) = 0;
3786 ADDTOCHAIN (ic);
3788 /* stack adjustment after call */
3789 ic->parmBytes = stack;
3791 if (!IS_STRUCT (type))
3793 IC_RESULT (ic) = newiTempOperand (type, 1);
3794 return IC_RESULT (ic);
3796 else
3798 symbol *sym = newSymbol (genSymName (ic->level), 1);
3799 sym->type = copyLinkChain (type);
3800 sym->etype = getSpec (sym->type);
3801 SPEC_SCLS (sym->etype) = S_AUTO;
3802 SPEC_OCLS (sym->etype) = NULL;
3803 SPEC_EXTR (sym->etype) = 0;
3804 SPEC_STAT (sym->etype) = 0;
3805 stack = allocVariables (sym);
3806 currFunc->stack += options.useXstack ? 0 : stack;
3807 currFunc->xstack += options.useXstack ? stack : 0;
3808 IC_RESULT (ic) = operandFromSymbol (sym, false);
3809 return (operandFromSymbol (sym, true));
3813 /*-----------------------------------------------------------------*/
3814 /* geniCodeReceive - generate intermediate code for "receive" */
3815 /*-----------------------------------------------------------------*/
3816 static void
3817 geniCodeReceive (value * args, operand * func)
3819 unsigned char paramByteCounter = 0;
3821 /* for all arguments that are passed in registers */
3822 while (args)
3824 if (IS_REGPARM (args->etype))
3826 operand *opr = operandFromValue (args, true);
3827 operand *opl;
3828 symbol *sym = OP_SYMBOL (opr);
3829 iCode *ic;
3831 /* we will use it after all optimizations
3832 and before liveRange calculation */
3833 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3836 if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE) &&
3837 options.stackAuto == 0 && (!(options.model == MODEL_FLAT24)))
3840 else
3842 opl = newiTempOperand (args->type, 0);
3843 sym->reqv = opl;
3844 sym->reqv->key = sym->key;
3845 OP_SYMBOL (sym->reqv)->key = sym->key;
3846 OP_SYMBOL (sym->reqv)->isreqv = 1;
3847 OP_SYMBOL (sym->reqv)->islocal = 0;
3848 SPIL_LOC (sym->reqv) = sym;
3852 ic = newiCode (RECEIVE, func, NULL);
3853 ic->argreg = SPEC_ARGREG (args->etype);
3854 if (ic->argreg == 1)
3856 currFunc->recvSize = getSize (sym->type);
3858 IC_RESULT (ic) = opr;
3860 /* misuse of parmBytes (normally used for functions)
3861 * to save estimated stack position of this argument.
3862 * Normally this should be zero for RECEIVE iCodes.
3863 * No idea if this causes side effects on other ports. - dw
3865 ic->parmBytes = paramByteCounter;
3867 /* what stack position do we have? */
3868 paramByteCounter += getSize (sym->type);
3870 ADDTOCHAIN (ic);
3873 args = args->next;
3877 /*-----------------------------------------------------------------*/
3878 /* geniCodeFunctionBody - create the function body */
3879 /*-----------------------------------------------------------------*/
3880 void
3881 geniCodeFunctionBody (ast * tree, int lvl)
3883 iCode *ic;
3884 operand *func;
3885 char *savefilename;
3886 int savelineno;
3887 short functionBlock;
3889 /* reset the auto generation */
3890 /* numbers */
3891 iTempNum = 0;
3892 iTempLblNum = 0;
3893 operandKey = 0;
3894 iCodeKey = 0;
3895 func = ast2iCode (tree->left, lvl + 1);
3897 savefilename = filename;
3898 savelineno = lineno;
3899 filename = OP_SYMBOL (func)->fileDef;
3900 lineno = OP_SYMBOL (func)->lineDef;
3901 /* create an entry label */
3902 geniCodeLabel (entryLabel);
3903 filename = savefilename;
3904 lineno = savelineno;
3906 /* create a proc icode */
3907 functionBlock = block;
3908 ic = newiCode (FUNCTION, func, NULL);
3909 filename = ic->filename = OP_SYMBOL (func)->fileDef;
3910 lineno = ic->lineno = OP_SYMBOL (func)->lineDef;
3911 ic->tree = tree;
3913 ADDTOCHAIN (ic);
3915 /* for all parameters that are passed
3916 on registers add a "receive" */
3917 geniCodeReceive (tree->values.args, func);
3919 /* generate code for the body */
3920 ast2iCode (tree->right, lvl + 1);
3922 /* create a label for return */
3923 block = functionBlock;
3924 geniCodeLabel (returnLabel);
3926 /* now generate the end proc */
3927 ic = newiCode (ENDFUNCTION, func, NULL);
3928 ic->filename = OP_SYMBOL (func)->fileDef;
3929 ic->lineno = OP_SYMBOL (func)->lastLine;
3930 ic->tree = tree;
3931 ADDTOCHAIN (ic);
3932 return;
3935 /*-----------------------------------------------------------------*/
3936 /* geniCodeReturn - gen icode for 'return' statement */
3937 /*-----------------------------------------------------------------*/
3938 void
3939 geniCodeReturn (operand * op)
3941 iCode *ic;
3943 /* return in _Noreturn function */
3944 if (currFunc && IFFUNC_ISNORETURN (currFunc->type))
3945 werror (W_NORETURNRETURN);
3947 /* check if a cast is needed */
3948 if (op && currFunc && currFunc->type && currFunc->type->next)
3949 checkPtrQualifiers (currFunc->type->next, operandType (op), !op->isConstElimnated);
3951 /* if the operand is present force an rvalue */
3952 if (op)
3953 op = geniCodeRValue (op, FALSE);
3955 ic = newiCode (RETURN, op, NULL);
3956 ADDTOCHAIN (ic);
3959 /*-----------------------------------------------------------------*/
3960 /* geniCodeIfx - generates code for extended if statement */
3961 /*-----------------------------------------------------------------*/
3962 void
3963 geniCodeIfx (ast * tree, int lvl)
3965 iCode *ic;
3966 operand *condition = ast2iCode (tree->left, lvl + 1);
3967 sym_link *cetype;
3969 /* if condition is null then exit */
3970 if (!condition)
3971 goto exit;
3972 else
3973 condition = geniCodeRValue (condition, FALSE);
3975 cetype = getSpec (operandType (condition));
3976 /* if the condition is a literal */
3977 if (IS_LITERAL (cetype))
3979 if (floatFromVal (OP_VALUE (condition)))
3981 if (tree->trueLabel)
3982 geniCodeGoto (tree->trueLabel);
3983 else
3984 assert (0);
3986 else
3988 if (tree->falseLabel)
3989 geniCodeGoto (tree->falseLabel);
3991 goto exit;
3994 if (tree->trueLabel)
3996 ic = newiCodeCondition (condition, tree->trueLabel, NULL);
3997 ADDTOCHAIN (ic);
3999 if (tree->falseLabel)
4000 geniCodeGoto (tree->falseLabel);
4002 else
4004 ic = newiCodeCondition (condition, NULL, tree->falseLabel);
4005 ADDTOCHAIN (ic);
4008 exit:
4009 if (tree->right && tree->right->type == EX_VALUE)
4010 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4011 else
4012 ast2iCode (tree->right, lvl + 1);
4015 /*-----------------------------------------------------------------*/
4016 /* geniCodeJumpTable - tries to create a jump table for switch */
4017 /*-----------------------------------------------------------------*/
4019 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
4021 int min, max, cnt = 1;
4022 int i, t;
4023 value *vch, *maxVal;
4024 iCode *ic;
4025 symbol *falseLabel;
4026 set *labels = NULL;
4027 sym_link *cetype = getSpec (operandType (cond));
4028 int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
4029 int sizeofMatchJump, sizeofJumpTable;
4030 int sizeIndex;
4031 struct dbuf_s dbuf;
4033 if (!tree || !caseVals)
4034 return 0;
4036 /* the criteria for creating a jump table is */
4037 /* all integer numbers between the maximum & minimum must */
4038 /* be present, the maximum value should not exceed 255 */
4039 /* If not all integer numbers are present the algorithm */
4040 /* inserts jumps to the default label for the missing numbers */
4041 /* and decides later whether it is worth it */
4042 min = (int) ulFromVal (vch = caseVals);
4044 while (vch->next)
4046 cnt++;
4047 vch = vch->next;
4049 max = (int) ulFromVal (vch);
4050 maxVal = vch;
4052 if (max-min < 0)
4053 return 0;
4054 /* Exit if the range is too large to handle with a jump table. */
4055 if (1 + max - min > port->jumptableCost.maxCount)
4056 return 0;
4058 switch (getSize (operandType (cond)))
4060 case 1:
4061 sizeIndex = 0;
4062 break;
4063 case 2:
4064 sizeIndex = 1;
4065 break;
4066 case 4:
4067 sizeIndex = 2;
4068 break;
4069 default:
4070 return 0;
4073 /* Compute the size cost of the range check and subtraction. */
4074 sizeofMinCost = 0;
4075 sizeofZeroMinCost = 0;
4076 sizeofMaxCost = 0;
4078 if (!(min == 0 && IS_UNSIGNED (cetype)))
4079 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4080 if (!IS_UNSIGNED (cetype))
4081 sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4082 sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4084 if (min)
4085 sizeofMinCost += port->jumptableCost.sizeofSubtract;
4087 /* If the size cost of handling a non-zero minimum exceeds the */
4088 /* cost of extending the range down to zero, then it might be */
4089 /* better to extend the range to zero. */
4090 if (min > 0 && (sizeofMinCost - sizeofZeroMinCost) >= (min * port->jumptableCost.sizeofElement))
4092 /* Only extend the jump table if it would still be manageable. */
4093 if (1 + max <= port->jumptableCost.maxCount)
4095 min = 0;
4096 if (IS_UNSIGNED (cetype))
4097 sizeofMinCost = 0;
4098 else
4099 sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
4103 /* Compute the total size cost of a jump table. */
4104 sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
4105 + port->jumptableCost.sizeofDispatch + sizeofMinCost + sizeofMaxCost;
4107 /* Compute the total size cost of a match & jump sequence */
4108 sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
4110 /* If the size cost of the jump table is uneconomical then exit */
4111 if (sizeofMatchJump < sizeofJumpTable)
4112 return 0;
4114 /* The jump table is preferable. */
4116 /* First, a label for the default or missing cases. */
4117 dbuf_init (&dbuf, 128);
4118 if (tree->values.switchVals.swDefault)
4120 dbuf_printf (&dbuf, "_default_%d%s", tree->values.switchVals.swNum,
4121 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4123 else
4125 dbuf_printf (&dbuf, "_swBrk_%d%s", tree->values.switchVals.swNum,
4126 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4128 falseLabel = newiTempLabel (dbuf_c_str (&dbuf));
4129 dbuf_destroy (&dbuf);
4131 /* Build the list of labels for the jump table. */
4132 vch = caseVals;
4133 t = (int) ulFromVal (vch);
4134 for (i = min; i <= max; i++)
4136 if (vch && t == i)
4138 dbuf_init (&dbuf, 128);
4139 /* Explicit case: make a new label for it. */
4140 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, i,
4141 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4142 addSet (&labels, newiTempLabel (dbuf_c_str (&dbuf)));
4143 dbuf_destroy (&dbuf);
4144 vch = vch->next;
4145 if (vch)
4146 t = (int) ulFromVal (vch);
4148 else
4150 /* Implicit case: use the default label. */
4151 addSet (&labels, falseLabel);
4155 /* first we rule out the boundary conditions */
4157 operand *lit;
4158 operand *boundary;
4159 sym_link *cetype = getSpec (operandType (cond));
4160 /* no need to check the lower bound if
4161 the condition is always >= min or
4162 the condition is unsigned & minimum value is zero */
4163 if ((checkConstantRange (cetype, caseVals->etype, '<', FALSE) != CCR_ALWAYS_FALSE) &&
4164 (!(min == 0 && IS_UNSIGNED (cetype))))
4166 lit = operandFromValue (valCastLiteral (cetype, min, min), false);
4167 boundary = geniCodeLogic (cond, lit, '<', NULL);
4168 ic = newiCodeCondition (boundary, falseLabel, NULL);
4169 ADDTOCHAIN (ic);
4172 /* now for upper bounds */
4173 if (checkConstantRange (cetype, maxVal->etype, '>', FALSE) != CCR_ALWAYS_FALSE)
4175 lit = operandFromValue (valCastLiteral (cetype, max, max), false);
4176 boundary = geniCodeLogic (cond, lit, '>', NULL);
4177 ic = newiCodeCondition (boundary, falseLabel, NULL);
4178 ADDTOCHAIN (ic);
4182 /* if the min is not zero then we now make it zero */
4183 if (min)
4185 cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
4186 if (!IS_LITERAL (getSpec (operandType (cond))))
4187 setOperandType (cond, UCHARTYPE);
4190 /* now create the jumptable */
4191 ic = newiCode (JUMPTABLE, NULL, NULL);
4192 IC_JTCOND (ic) = cond;
4193 IC_JTLABELS (ic) = labels;
4194 ADDTOCHAIN (ic);
4195 return 1;
4198 /*-----------------------------------------------------------------*/
4199 /* geniCodeSwitch - changes a switch to a if statement */
4200 /*-----------------------------------------------------------------*/
4201 void
4202 geniCodeSwitch (ast * tree, int lvl)
4204 iCode *ic;
4205 operand *cond = geniCodeRValue (ast2iCode (tree->left, lvl + 1), FALSE);
4206 value *caseVals = tree->values.switchVals.swVals;
4207 symbol *trueLabel, *falseLabel;
4208 struct dbuf_s dbuf;
4210 /* If the condition is a literal, then just jump to the */
4211 /* appropriate case label. */
4212 if (IS_LITERAL (getSpec (operandType (cond))))
4214 int switchVal, caseVal;
4216 switchVal = (int) ulFromVal (OP_VALUE (cond));
4217 while (caseVals)
4219 caseVal = (int) ulFromVal (caseVals);
4220 if (caseVal == switchVal)
4222 struct dbuf_s dbuf;
4224 dbuf_init (&dbuf, 128);
4225 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, caseVal,
4226 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4227 trueLabel = newiTempLabel (dbuf_c_str (&dbuf));
4228 dbuf_destroy (&dbuf);
4229 geniCodeGoto (trueLabel);
4230 goto jumpTable;
4232 caseVals = caseVals->next;
4234 goto defaultOrBreak;
4237 /* If cond is volatile, it might change while we are trying to */
4238 /* find the matching case. To avoid this possibility, make a */
4239 /* non-volatile copy to use instead. */
4240 if (IS_OP_VOLATILE (cond))
4242 operand *newcond;
4243 iCode *ic;
4245 newcond = newiTempOperand (operandType (cond), TRUE);
4246 newcond->isvolatile = 0;
4247 ic = newiCode ('=', NULL, cond);
4248 IC_RESULT (ic) = newcond;
4249 ADDTOCHAIN (ic);
4250 cond = newcond;
4253 /* if we can make this a jump table */
4254 if (geniCodeJumpTable (cond, caseVals, tree))
4255 goto jumpTable; /* no need for the comparison */
4257 /* for the cases defined do */
4258 while (caseVals)
4260 operand *compare = geniCodeLogic (cond, operandFromValue (caseVals, true), EQ_OP, NULL);
4262 dbuf_init (&dbuf, 128);
4263 dbuf_printf (&dbuf, "_case_%d_%d%s", tree->values.switchVals.swNum, (int) ulFromVal (caseVals),
4264 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4265 trueLabel = newiTempLabel (dbuf_c_str (&dbuf));
4266 dbuf_destroy (&dbuf);
4268 ic = newiCodeCondition (compare, trueLabel, NULL);
4269 ADDTOCHAIN (ic);
4270 caseVals = caseVals->next;
4273 defaultOrBreak:
4274 /* if default is present then goto break else break */
4275 dbuf_init (&dbuf, 128);
4276 if (tree->values.switchVals.swDefault)
4278 dbuf_printf (&dbuf, "_default_%d%s", tree->values.switchVals.swNum,
4279 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4281 else
4283 dbuf_printf (&dbuf, "_swBrk_%d%s", tree->values.switchVals.swNum,
4284 tree->values.switchVals.swSuffix ? tree->values.switchVals.swSuffix : "");
4287 falseLabel = newiTempLabel (dbuf_c_str (&dbuf));
4288 dbuf_destroy (&dbuf);
4289 geniCodeGoto (falseLabel);
4291 jumpTable:
4292 ast2iCode (tree->right, lvl + 1);
4295 /*-----------------------------------------------------------------*/
4296 /* geniCodeInline - intermediate code for inline assembler */
4297 /*-----------------------------------------------------------------*/
4298 static void
4299 geniCodeInline (ast * tree)
4301 iCode *ic;
4303 ic = newiCode (INLINEASM, NULL, NULL);
4304 IC_INLINE (ic) = tree->values.inlineasm;
4305 ADDTOCHAIN (ic);
4308 /*-----------------------------------------------------------------*/
4309 /* geniCodeArrayInit - intermediate code for array initializer */
4310 /*-----------------------------------------------------------------*/
4311 static void
4312 geniCodeArrayInit (ast * tree, operand * array)
4314 iCode *ic;
4316 if (!getenv ("TRY_THE_NEW_INITIALIZER"))
4318 ic = newiCode (ARRAYINIT, array, NULL);
4319 IC_ARRAYILIST (ic) = tree->values.constlist;
4321 else
4323 operand *left = newOperand (), *right = newOperand ();
4324 left->type = right->type = SYMBOL;
4325 OP_SYMBOL (left) = AST_SYMBOL (tree->left);
4326 OP_SYMBOL (right) = AST_SYMBOL (tree->right);
4327 ic = newiCode (ARRAYINIT, left, right);
4329 ADDTOCHAIN (ic);
4332 /*-----------------------------------------------------------------*/
4333 /* geniCodeCritical - intermediate code for a critical statement */
4334 /*-----------------------------------------------------------------*/
4335 static void
4336 geniCodeCritical (ast * tree, int lvl)
4338 iCode *ic;
4339 operand *op = NULL;
4340 sym_link *type;
4342 if (!options.stackAuto && !TARGET_HC08_LIKE && !TARGET_MOS6502_LIKE)
4344 type = newLink (SPECIFIER);
4345 SPEC_VOLATILE (type) = 1;
4346 SPEC_NOUN (type) = V_BIT;
4347 SPEC_SCLS (type) = S_BIT;
4348 SPEC_BLEN (type) = 1;
4349 SPEC_BSTR (type) = 0;
4350 op = newiTempOperand (type, 1);
4353 /* If op is NULL, the original interrupt state will saved on */
4354 /* the stack. Otherwise, it will be saved in op. */
4356 /* Generate a save of the current interrupt state & disable */
4357 inCriticalPair = 1;
4358 ic = newiCode (CRITICAL, NULL, NULL);
4359 IC_RESULT (ic) = op;
4360 ADDTOCHAIN (ic);
4362 /* Generate the critical code sequence */
4363 if (tree->left && tree->left->type == EX_VALUE)
4364 geniCodeDummyRead (ast2iCode (tree->left, lvl + 1));
4365 else
4366 ast2iCode (tree->left, lvl + 1);
4368 /* Generate a restore of the original interrupt state */
4369 ic = newiCode (ENDCRITICAL, NULL, op);
4370 ADDTOCHAIN (ic);
4371 inCriticalPair = 0;
4374 /*-----------------------------------------------------------------*/
4375 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
4376 /* particular case. Ie : assigning or dereferencing array or ptr */
4377 /*-----------------------------------------------------------------*/
4378 set *lvaluereqSet = NULL;
4379 typedef struct lvalItem
4381 int req;
4382 int lvl;
4384 lvalItem;
4386 /*-----------------------------------------------------------------*/
4387 /* addLvaluereq - add a flag for lvalreq for current ast level */
4388 /*-----------------------------------------------------------------*/
4389 static void
4390 addLvaluereq (int lvl)
4392 lvalItem *lpItem = (lvalItem *) Safe_alloc (sizeof (lvalItem));
4393 lpItem->req = 1;
4394 lpItem->lvl = lvl;
4395 addSetHead (&lvaluereqSet, lpItem);
4398 /*-----------------------------------------------------------------*/
4399 /* delLvaluereq - del a flag for lvalreq for current ast level */
4400 /*-----------------------------------------------------------------*/
4401 static void
4402 delLvaluereq ()
4404 lvalItem *lpItem = getSet (&lvaluereqSet);
4405 if (lpItem)
4406 Safe_free (lpItem);
4409 /*-----------------------------------------------------------------*/
4410 /* clearLvaluereq - clear lvalreq flag */
4411 /*-----------------------------------------------------------------*/
4412 static void
4413 clearLvaluereq ()
4415 lvalItem *lpItem = peekSet (lvaluereqSet);
4416 if (lpItem)
4417 lpItem->req = 0;
4420 /*-----------------------------------------------------------------*/
4421 /* getLvaluereq - get the last lvalreq level */
4422 /*-----------------------------------------------------------------*/
4423 #if 0
4425 getLvaluereqLvl ()
4427 lvalItem *lpItem = peekSet (lvaluereqSet);
4428 if (lpItem)
4429 return lpItem->lvl;
4430 return 0;
4432 #endif
4433 /*-----------------------------------------------------------------*/
4434 /* isLvaluereq - is lvalreq valid for this level ? */
4435 /*-----------------------------------------------------------------*/
4436 static int
4437 isLvaluereq (int lvl)
4439 lvalItem *lpItem = peekSet (lvaluereqSet);
4440 if (lpItem)
4441 return ((lpItem->req) && (lvl <= (lpItem->lvl + 1)));
4442 return 0;
4445 /*-----------------------------------------------------------------*/
4446 /* ast2iCode - creates an icodeList from an ast */
4447 /*-----------------------------------------------------------------*/
4448 operand *
4449 ast2iCode (ast * tree, int lvl)
4451 operand *left = NULL;
4452 operand *right = NULL;
4453 if (!tree)
4454 return NULL;
4456 /* set the global variables for filename & line number */
4457 if (tree->filename)
4458 filename = tree->filename;
4459 if (tree->lineno)
4460 lineno = tree->lineno;
4461 if (tree->block)
4462 block = tree->block;
4463 if (tree->level)
4464 scopeLevel = tree->level;
4465 if (tree->seqPoint)
4466 seqPoint = tree->seqPoint;
4468 if (tree->type == EX_VALUE)
4469 return operandFromValue (tree->opval.val, true);
4471 if (tree->type == EX_LINK)
4472 return operandFromLink (tree->opval.lnk);
4474 /* if we find a nullop */
4475 if (tree->type == EX_OP && (tree->opval.op == NULLOP || tree->opval.op == BLOCK))
4477 int oldInlinedActive = inlinedActive;
4478 if (tree->inlined)
4479 inlinedActive = 1;
4480 if (tree->left && tree->left->type == EX_VALUE)
4481 geniCodeDummyRead (ast2iCode (tree->left, lvl + 1));
4482 else
4483 ast2iCode (tree->left, lvl + 1);
4484 if (tree->right && tree->right->type == EX_VALUE)
4485 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4486 else
4487 ast2iCode (tree->right, lvl + 1);
4488 inlinedActive = oldInlinedActive;
4489 return NULL;
4492 /* special cases for not evaluating */
4493 if (tree->opval.op != ':' &&
4494 tree->opval.op != '?' &&
4495 tree->opval.op != CALL &&
4496 tree->opval.op != IFX &&
4497 tree->opval.op != AND_OP &&
4498 tree->opval.op != OR_OP &&
4499 tree->opval.op != LABEL &&
4500 tree->opval.op != GOTO &&
4501 tree->opval.op != SWITCH && tree->opval.op != FUNCTION && tree->opval.op != INLINEASM && tree->opval.op != CRITICAL)
4503 if (IS_ASSIGN_OP (tree->opval.op) || IS_DEREF_OP (tree) || IS_ADDRESS_OF_OP (tree))
4505 addLvaluereq (lvl);
4506 if ((!IS_ADDRESS_OF_OP (tree) && IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left) &&
4507 tree->left->left->ftype && IS_ARRAY (tree->left->left->ftype) &&
4508 tree->left->left->ftype->next && IS_ARRAY (tree->left->left->ftype->next)) ||
4509 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4510 clearLvaluereq ();
4512 left = operandFromAst (tree->left, lvl, true);
4513 delLvaluereq ();
4514 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4515 left = geniCodeRValue (left, TRUE);
4517 else
4519 left = operandFromAst (tree->left, lvl, true);
4521 if (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)
4523 addLvaluereq (lvl);
4524 right = operandFromAst (tree->right, lvl, true);
4525 delLvaluereq ();
4527 else
4529 right = operandFromAst (tree->right, lvl, tree->opval.op != RETURN);
4533 /* now depending on the type of operand */
4534 /* this will be a biggy */
4535 switch (tree->opval.op)
4537 case '[': /* array operation */
4539 //sym_link *ltype = operandType (left);
4540 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4541 left = geniCodeRValue (left, FALSE);
4542 right = geniCodeRValue (right, TRUE);
4545 return geniCodeArray (left, right, lvl, false);
4547 case '.': /* structure dereference */
4548 if (IS_PTR (operandType (left)))
4549 left = geniCodeRValue (left, TRUE);
4550 else
4551 left = geniCodeRValue (left, FALSE);
4553 return geniCodeStruct (left, right, tree->lvalue);
4555 case PTR_OP: /* structure pointer dereference */
4557 sym_link *pType;
4558 pType = operandType (left);
4559 left = geniCodeRValue (left, TRUE);
4561 setOClass (pType, getSpec (operandType (left)));
4564 return geniCodeStruct (left, right, tree->lvalue);
4566 case INC_OP: /* increment operator */
4567 if (left)
4568 return geniCodePostInc (left);
4569 else
4570 return geniCodePreInc (right, tree->lvalue);
4572 case DEC_OP: /* decrement operator */
4573 if (left)
4574 return geniCodePostDec (left);
4575 else
4576 return geniCodePreDec (right, tree->lvalue);
4578 case '&': /* bitwise and or address of operator */
4579 if (right)
4580 { /* this is a bitwise operator */
4581 left = geniCodeRValue (left, FALSE);
4582 right = geniCodeRValue (right, FALSE);
4583 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4585 else
4586 return geniCodeAddressOf (left);
4588 case '|': /* bitwise or & xor */
4589 case '^':
4590 return geniCodeBitwise (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), tree->opval.op, tree->ftype);
4592 case '/':
4593 return geniCodeDivision (geniCodeRValue (left, FALSE),
4594 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), false);
4596 case '%':
4597 return geniCodeModulus (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4598 case '*':
4599 if (right)
4600 return geniCodeMultiply (geniCodeRValue (left, FALSE),
4601 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4602 else
4603 return geniCodeDerefPtr (geniCodeRValue (left, FALSE), lvl);
4605 case '-':
4606 if (right)
4607 return geniCodeSubtract (geniCodeRValue (left, FALSE),
4608 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4609 else
4610 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4612 case '+':
4613 if (right)
4614 return geniCodeAdd (geniCodeRValue (left, FALSE),
4615 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), lvl);
4616 else
4617 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
4619 case LEFT_OP:
4620 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4621 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype));
4623 case RIGHT_OP:
4624 return geniCodeRightShift (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE));
4625 case CAST:
4626 #if 0 // this indeed needs a second thought
4628 operand *op;
4630 // let's keep this simple: get the rvalue we need
4631 op = geniCodeRValue (right, FALSE);
4632 // now cast it to whatever we want
4633 op = geniCodeCast (operandType (left), op, FALSE);
4634 // if this is going to be used as an lvalue, make it so
4635 if (tree->lvalue)
4637 op->isaddr = 1;
4639 return op;
4641 #else // bug #604575, is it a bug ????
4642 return geniCodeCast (operandType (left), geniCodeRValue (right, FALSE), FALSE);
4643 #endif
4645 case '~':
4646 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op, tree->ftype);
4648 case '!':
4650 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op, tree->ftype);
4651 return op;
4653 case ROT:
4655 operand *op = geniCodeBinary (geniCodeRValue (left, false),
4656 geniCodeRValue (right, false),
4657 tree->opval.op, tree->ftype);
4658 return op;
4660 case GETABIT:
4662 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4663 geniCodeRValue (right, FALSE),
4664 tree->opval.op, tree->ftype);
4665 return op;
4667 case GETBYTE:
4669 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4670 geniCodeRValue (right, FALSE),
4671 tree->opval.op, tree->ftype);
4672 setOperandType (op, UCHARTYPE);
4673 return op;
4675 case GETWORD:
4677 operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4678 geniCodeRValue (right, FALSE),
4679 tree->opval.op, tree->ftype);
4680 setOperandType (op, UINTTYPE);
4681 return op;
4683 case AND_OP:
4684 case OR_OP:
4685 return geniCodeLogicAndOr (tree, lvl);
4686 case '>':
4687 case '<':
4688 case LE_OP:
4689 case GE_OP:
4690 case EQ_OP:
4691 case NE_OP:
4692 /* different compilers (even different gccs) evaluate
4693 the two calls in a different order. to get the same
4694 result on all machines we have to specify a clear sequence.
4695 return geniCodeLogic (geniCodeRValue (left, FALSE),
4696 geniCodeRValue (right, FALSE),
4697 tree->opval.op);
4700 operand *leftOp, *rightOp;
4702 leftOp = geniCodeRValue (left, FALSE);
4703 rightOp = geniCodeRValue (right, FALSE);
4705 return geniCodeLogic (leftOp, rightOp, tree->opval.op, tree);
4707 case '?':
4708 return geniCodeConditional (tree, lvl);
4710 case SIZEOF:
4711 return operandFromLit (getSize (tree->right->ftype));
4713 case '=':
4715 sym_link *rtype = operandType (right);
4716 sym_link *ltype = operandType (left);
4717 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4718 right = geniCodeRValue (right, TRUE);
4719 else
4720 right = geniCodeRValue (right, FALSE);
4721 return geniCodeAssign (left, right, 0, 1);
4723 case MUL_ASSIGN:
4724 return
4725 geniCodeAssign (left,
4726 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4727 FALSE),
4728 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4730 case DIV_ASSIGN:
4731 return
4732 geniCodeAssign (left,
4733 geniCodeDivision (geniCodeRValue (operandFromOperand (left), FALSE),
4734 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype), false), 0, 1);
4735 case MOD_ASSIGN:
4736 return
4737 geniCodeAssign (left,
4738 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4739 FALSE),
4740 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4741 case ADD_ASSIGN:
4743 sym_link *rtype = operandType (right);
4744 sym_link *ltype = operandType (left);
4745 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4746 right = geniCodeRValue (right, TRUE);
4747 else
4748 right = geniCodeRValue (right, FALSE);
4751 return geniCodeAssign (left,
4752 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4753 FALSE), right, getResultTypeFromType (tree->ftype), lvl), 0, 1);
4755 case SUB_ASSIGN:
4757 sym_link *rtype = operandType (right);
4758 sym_link *ltype = operandType (left);
4759 if (IS_PTR (rtype) && IS_ITEMP (right) && right->isaddr && compareType (rtype->next, ltype, false) == 1)
4761 right = geniCodeRValue (right, TRUE);
4763 else
4765 right = geniCodeRValue (right, FALSE);
4767 return
4768 geniCodeAssign (left,
4769 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4770 FALSE), right, getResultTypeFromType (tree->ftype)), 0, 1);
4772 case LEFT_ASSIGN:
4773 return
4774 geniCodeAssign (left,
4775 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left), FALSE),
4776 geniCodeRValue (right, FALSE), getResultTypeFromType (tree->ftype)), 0, 1);
4777 case RIGHT_ASSIGN:
4778 return
4779 geniCodeAssign (left,
4780 geniCodeRightShift (geniCodeRValue (operandFromOperand (left), FALSE),
4781 geniCodeRValue (right, FALSE)), 0, 1);
4782 case AND_ASSIGN:
4783 return
4784 geniCodeAssign (left,
4785 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4786 FALSE),
4787 geniCodeRValue (right, FALSE), BITWISEAND, operandType (left)), 0, 1);
4788 case XOR_ASSIGN:
4789 return
4790 geniCodeAssign (left,
4791 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4792 FALSE), geniCodeRValue (right, FALSE), '^', operandType (left)), 0, 1);
4793 case OR_ASSIGN:
4794 return
4795 geniCodeAssign (left,
4796 geniCodeBitwise (geniCodeRValue (operandFromOperand (left), FALSE),
4797 geniCodeRValue (right, FALSE), '|', operandType (left)), 0, 1);
4798 case ',':
4799 return geniCodeRValue (right, FALSE);
4801 case CALL:
4802 return geniCodeCall (ast2iCode (tree->left, lvl + 1), tree->right, lvl);
4804 case LABEL:
4805 geniCodeLabel (OP_SYMBOL (ast2iCode (tree->left, lvl + 1)));
4806 if (tree->right && tree->right->type == EX_VALUE)
4808 geniCodeDummyRead (ast2iCode (tree->right, lvl + 1));
4809 return NULL;
4811 else
4812 return ast2iCode (tree->right, lvl + 1);
4814 case GOTO:
4815 geniCodeGoto (OP_SYMBOL (ast2iCode (tree->left, lvl + 1)));
4816 return ast2iCode (tree->right, lvl + 1);
4818 case FUNCTION:
4819 geniCodeFunctionBody (tree, lvl);
4820 return NULL;
4822 case RETURN:
4823 geniCodeReturn (right);
4824 return NULL;
4826 case IFX:
4827 geniCodeIfx (tree, lvl);
4828 return NULL;
4830 case SWITCH:
4831 geniCodeSwitch (tree, lvl);
4832 return NULL;
4834 case INLINEASM:
4835 geniCodeInline (tree);
4836 return NULL;
4838 case ARRAYINIT:
4839 geniCodeArrayInit (tree, ast2iCode (tree->left, lvl + 1));
4840 return NULL;
4842 case CRITICAL:
4843 geniCodeCritical (tree, lvl);
4846 return NULL;
4849 /*-----------------------------------------------------------------*/
4850 /* iCodeFromAst - given an ast will convert it to iCode */
4851 /*-----------------------------------------------------------------*/
4852 iCode *
4853 iCodeFromAst (ast * tree)
4855 returnLabel = newiTempLabel ("_return");
4856 entryLabel = newiTempLabel ("_entry");
4857 iCodeChain = 0;
4858 ast2iCode (tree, 0);
4859 return (iCodeChain);
4862 static const char *
4863 opTypeToStr (OPTYPE op)
4865 switch (op)
4867 case SYMBOL:
4868 return "symbol";
4869 case VALUE:
4870 return "value";
4871 case TYPE:
4872 return "type";
4874 return "undefined type";
4878 operand *
4879 validateOpType (operand *op, const char *macro, const char *args, OPTYPE type, const char *file, unsigned line)
4881 if (op && op->type == type)
4883 return op;
4885 fprintf (stderr,
4886 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4887 " expected %s, got %s\n", macro, args, file, line, opTypeToStr (type), op ? opTypeToStr (op->type) : "null op");
4888 exit (EXIT_FAILURE);
4889 return op; // never reached, makes compiler happy.
4892 const operand *
4893 validateOpTypeConst (const operand *op, const char *macro, const char *args, OPTYPE type, const char *file, unsigned line)
4895 if (op && op->type == type)
4897 return op;
4899 fprintf (stderr,
4900 "Internal error: validateOpTypeConst failed in %s(%s) @ %s:%u:"
4901 " expected %s, got %s\n", macro, args, file, line, opTypeToStr (type), op ? opTypeToStr (op->type) : "null op");
4902 exit (EXIT_FAILURE);
4903 return op; // never reached, makes compiler happy.