1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
28 #include "dbuf_string.h"
30 /*-----------------------------------------------------------------*/
31 /* global variables */
33 iCode
*iCodeChain
= 0;
40 char *filename
; /* current file name */
41 int lineno
= 1; /* current line number */
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
);
70 PRINTFUNC (picAssign
);
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.
135 ADDTOCHAIN (iCode
*x
)
143 iCodeChainEnd
->next
= x
;
145 x
->prev
= iCodeChainEnd
;
150 /*-----------------------------------------------------------------*/
151 /* operandName - returns the name of the operand */
152 /*-----------------------------------------------------------------*/
154 printOperand (operand
* op
, FILE * file
)
165 dbuf_init (&dbuf
, 1024);
166 ret
= dbuf_printOperand (op
, &dbuf
);
167 dbuf_write_and_destroy (&dbuf
, file
);
176 dbuf_printOperand (operand
* op
, struct dbuf_s
*dbuf
)
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
);
194 dbuf_printf (dbuf
, "0x%x {", (unsigned int) ulFromVal (OP_VALUE (op
)));
195 dbuf_printTypeChain (operandType (op
), dbuf
);
196 dbuf_append_char (dbuf
, '}');
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
),
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
));
233 dbuf_append_str (dbuf
, "[err]");
235 dbuf_append_str (dbuf
, "[remat]");
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
));
249 dbuf_append_str (dbuf
, "[err]");
252 dbuf_append_char (dbuf
, ']');
255 //#else /* } 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
));
286 dbuf_append_str (dbuf
, "[err]");
288 dbuf_append_str (dbuf
, "[remat]");
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
, ']');
304 dbuf_append_char (dbuf
, '(');
305 dbuf_printTypeChain (OP_TYPE (op
), dbuf
);
306 dbuf_append_char (dbuf
, ')');
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
);
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
);
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
, " = ");
363 dbuf_append_str (dbuf
, " = &[");
364 dbuf_printOperand (IC_LEFT (ic
), dbuf
);
367 if (IS_ITEMP (IC_LEFT (ic
)))
368 dbuf_append_str (dbuf
, " offsetAdd ");
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');
376 dbuf_append_str (dbuf
, "]\n");
379 PRINTFUNC (picJumpTable
)
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');
407 dbuf_printOperand (IC_RESULT (ic
), dbuf
);
408 dbuf_append_str (dbuf
, " = ");
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
);
426 dbuf_printf (dbuf
, "{parmPush = %d}", ic
->parmPush
);
428 dbuf_append_char (dbuf
, '\n');
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');
462 dbuf_printf (dbuf
, " %s($%d) :\n", IC_LABEL (ic
)->name
, IC_LABEL (ic
)->key
);
467 dbuf_append_char (dbuf
, '\t');
468 dbuf_printf (dbuf
, " goto %s($%d)\n", IC_LABEL (ic
)->name
, IC_LABEL (ic
)->key
);
473 dbuf_append_char (dbuf
, '\t');
474 dbuf_append_str (dbuf
, "if ");
475 dbuf_printOperand (IC_COND (ic
), dbuf
);
478 dbuf_printf (dbuf
, " == 0 goto %s($%d)\n", IC_FALSE (ic
)->name
, IC_FALSE (ic
)->key
);
481 dbuf_printf (dbuf
, " != 0 goto %s($%d)", IC_TRUE (ic
)->name
, IC_TRUE (ic
)->key
);
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');
513 dbuf_printOperand (IC_RESULT (ic
), dbuf
);
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
);
525 dbuf_printOperand (IC_RIGHT (ic
), dbuf
);
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
)
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
);
554 printiCChain (ic
, stdout
);
557 /*-----------------------------------------------------------------*/
558 /* printiCChain - prints intermediate code for humans */
559 /*-----------------------------------------------------------------*/
561 printiCChain (iCode
* icChain
, FILE * of
)
568 for (loop
= icChain
; loop
; loop
= loop
->next
)
570 if ((icTab
= getTableEntry (loop
->op
)))
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
);
587 /*-----------------------------------------------------------------*/
588 /* newOperand - allocate, init & return a new iCode */
589 /*-----------------------------------------------------------------*/
595 op
= Safe_alloc (sizeof (operand
));
601 /*-----------------------------------------------------------------*/
602 /* newiCode - create and return a new iCode entry initialized */
603 /*-----------------------------------------------------------------*/
605 newiCode (int op
, operand
*left
, operand
*right
)
609 ic
= Safe_alloc (sizeof (iCode
));
611 ic
->seqPoint
= seqPoint
;
612 ic
->filename
= filename
;
615 ic
->level
= scopeLevel
;
617 ic
->key
= iCodeKey
++;
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;
627 ic
->resultvalinfo
= 0;
632 /*-----------------------------------------------------------------*/
633 /* newiCode for conditional statements */
634 /*-----------------------------------------------------------------*/
636 newiCodeCondition (operand
* condition
, symbol
* trueLabel
, symbol
* falseLabel
)
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
;
652 /*-----------------------------------------------------------------*/
653 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
654 /*-----------------------------------------------------------------*/
656 newiCodeLabelGoto (int op
, symbol
* label
)
660 ic
= newiCode (op
, NULL
, NULL
);
664 IC_RIGHT (ic
) = NULL
;
665 IC_RESULT (ic
) = NULL
;
669 /*-----------------------------------------------------------------*/
670 /* newiTemp - allocate & return a newItemp Variable */
671 /*-----------------------------------------------------------------*/
673 newiTemp (const char *s
)
678 dbuf_init (&dbuf
, 128);
680 dbuf_append_str (&dbuf
, s
);
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
);
692 /*-----------------------------------------------------------------*/
693 /* newiTempLabel - creates a temp variable label */
694 /*-----------------------------------------------------------------*/
696 newiTempLabel (const char *s
)
700 /* check if this already exists */
701 if (s
&& (itmplbl
= findSym (LabelTab
, NULL
, s
)))
706 itmplbl
= newSymbol (s
, 1);
712 dbuf_init (&dbuf
, 128);
713 dbuf_printf (&dbuf
, "iTempLbl%d", iTempLblNum
++);
714 itmplbl
= newSymbol (dbuf_c_str (&dbuf
), 1);
715 dbuf_destroy (&dbuf
);
720 itmplbl
->key
= labelKey
++;
721 addSym (LabelTab
, itmplbl
, itmplbl
->name
, 0, 0, 0);
725 /*-----------------------------------------------------------------*/
726 /* newiTempLoopHeaderLabel - creates a new loop header label */
727 /*-----------------------------------------------------------------*/
729 newiTempLoopHeaderLabel (bool pre
)
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
);
741 itmplbl
->key
= labelKey
++;
742 addSym (LabelTab
, itmplbl
, itmplbl
->name
, 0, 0, 0);
747 /*-----------------------------------------------------------------*/
748 /* initiCode - initializes some iCode related stuff */
749 /*-----------------------------------------------------------------*/
756 /*-----------------------------------------------------------------*/
757 /* copyiCode - make a copy of the iCode given */
758 /*-----------------------------------------------------------------*/
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 */
774 IC_COND (nic
) = operandFromOperand (IC_COND (ic
));
775 IC_TRUE (nic
) = IC_TRUE (ic
);
776 IC_FALSE (nic
) = IC_FALSE (ic
);
780 IC_JTCOND (nic
) = operandFromOperand (IC_JTCOND (ic
));
781 IC_JTLABELS (nic
) = IC_JTLABELS (ic
);
786 IC_RESULT (nic
) = operandFromOperand (IC_RESULT (ic
));
787 IC_LEFT (nic
) = operandFromOperand (IC_LEFT (ic
));
791 IC_INLINE (nic
) = IC_INLINE (ic
);
795 IC_ARRAYILIST (nic
) = IC_ARRAYILIST (ic
);
799 IC_RESULT (nic
) = operandFromOperand (IC_RESULT (ic
));
800 IC_LEFT (nic
) = operandFromOperand (IC_LEFT (ic
));
801 IC_RIGHT (nic
) = operandFromOperand (IC_RIGHT (ic
));
807 /*-----------------------------------------------------------------*/
808 /* getTableEntry - gets the table entry for the given operator */
809 /*-----------------------------------------------------------------*/
811 getTableEntry (int oper
)
815 for (i
= 0; i
< (sizeof (codeTable
) / sizeof (iCodeTable
)); i
++)
816 if (oper
== codeTable
[i
].icode
)
817 return &codeTable
[i
];
822 /*-----------------------------------------------------------------*/
823 /* newiTempOperand - new intermediate temp operand */
824 /*-----------------------------------------------------------------*/
826 newiTempOperand (sym_link
* type
, char throwType
)
829 operand
*op
= newOperand ();
833 itmp
= newiTemp (NULL
);
835 etype
= getSpec (type
);
837 if (IS_LITERAL (etype
))
840 /* copy the type information */
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;
850 SPEC_ADDRSPACE (itmp
->etype
) = 0;
852 op
->svt
.symOperand
= itmp
;
853 op
->key
= itmp
->key
= ++operandKey
;
857 /*-----------------------------------------------------------------*/
858 /* operandType - returns the type chain for an operand */
859 /*-----------------------------------------------------------------*/
861 operandType (const operand
*op
)
865 /* depending on type of operand */
869 return op
->svt
.valOperand
->type
;
872 return op
->svt
.symOperand
->type
;
875 return op
->svt
.typeOperand
;
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 /*-----------------------------------------------------------------*/
889 operandSize (operand
* op
)
893 /* if nothing return 0 */
897 type
= operandType (op
);
898 if (op
->aggr2ptr
== 2)
900 return getSize (type
);
903 /*-----------------------------------------------------------------*/
904 /* isParamterToCall - will return 1 if op is a parameter to args */
905 /*-----------------------------------------------------------------*/
907 isParameterToCall (value
* args
, operand
* op
)
911 wassert (IS_SYMOP (op
));
915 if (tval
->sym
&& isSymbolEqual (OP_SYMBOL (op
), tval
->sym
))
922 /*-----------------------------------------------------------------*/
923 /* isOperandGlobal - return 1 if operand is a global variable */
924 /*-----------------------------------------------------------------*/
926 isOperandGlobal (const operand
*op
)
935 (op
->svt
.symOperand
->level
== 0 || IS_STATIC (op
->svt
.symOperand
->etype
) || IS_EXTERN (op
->svt
.symOperand
->etype
)))
941 /*-----------------------------------------------------------------*/
942 /* isOperandVolatile - return 1 if the operand is volatile */
943 /*-----------------------------------------------------------------*/
945 isOperandVolatile (const operand
*op
, bool chkTemp
)
950 if (IS_ITEMP (op
) && !chkTemp
)
953 return IS_VOLATILE (operandType (op
));
956 /*-----------------------------------------------------------------*/
957 /* isOperandLiteral - returns 1 if an operand contains a literal */
958 /*-----------------------------------------------------------------*/
960 isOperandLiteral (const operand
*const op
)
967 opetype
= getSpec (operandType (op
));
969 if (IS_LITERAL (opetype
))
975 /*-----------------------------------------------------------------*/
976 /* isOperandInFarSpace - will return true if operand is in farSpace */
977 /*-----------------------------------------------------------------*/
979 isOperandInFarSpace (operand
* op
)
989 if (!IS_TRUE_SYMOP (op
))
992 etype
= SPIL_LOC (op
)->etype
;
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 /*-----------------------------------------------------------------*/
1007 isOperandInPagedSpace (operand
* op
)
1017 if (!IS_TRUE_SYMOP (op
))
1020 etype
= SPIL_LOC (op
)->etype
;
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 /*------------------------------------------------------------------*/
1035 isOperandInDirSpace (operand
* op
)
1045 if (!IS_TRUE_SYMOP (op
))
1048 etype
= SPIL_LOC (op
)->etype
;
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 /*-----------------------------------------------------------------*/
1063 isOperandInBitSpace (operand
* op
)
1073 if (!IS_TRUE_SYMOP (op
))
1076 etype
= SPIL_LOC (op
)->etype
;
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 /*--------------------------------------------------------------------*/
1091 isOperandInCodeSpace (operand
* op
)
1101 etype
= getSpec (operandType (op
));
1103 if (!IS_TRUE_SYMOP (op
))
1106 etype
= SPIL_LOC (op
)->etype
;
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 /*-----------------------------------------------------------------*/
1121 isOperandOnStack (operand
* op
)
1131 etype
= getSpec (operandType (op
));
1132 if (IN_STACK (etype
) || OP_SYMBOL (op
)->onStack
|| (SPIL_LOC (op
) && SPIL_LOC (op
)->onStack
))
1139 /*-------------------------------------------------------------------*/
1140 /* detachiCodeOperand - remove a specific operand position (left, */
1141 /* right, result) from an iCode and update */
1142 /* the uses & defs as appropriate. */
1143 /*-------------------------------------------------------------------*/
1145 detachiCodeOperand (operand
**opp
, iCode
*ic
)
1152 bool ispointerset
= POINTER_SET (ic
);
1154 if (!ispointerset
&& (opp
== &ic
->result
))
1155 bitVectUnSetBit (OP_DEFS (op
), ic
->key
);
1157 if (ispointerset
&& (op
== ic
->result
))
1161 if (op
== ic
->right
)
1164 bitVectUnSetBit (OP_USES (op
), ic
->key
);
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 /*-------------------------------------------------------------------*/
1179 attachiCodeOperand (operand
*newop
, operand
**opp
, iCode
*ic
)
1181 /* If there is already an operand here, detach it first */
1183 detachiCodeOperand (opp
, ic
);
1185 /* Insert new operand */
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
);
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 /*-----------------------------------------------------------------*/
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
)
1224 /* Find the next CALL/PCALL */
1227 if (lic
->op
== CALL
|| lic
->op
== PCALL
)
1235 /* A function call was found. Scan backwards and see if an */
1236 /* IPUSH or SEND is encountered */
1239 if (lic
!= ic
&& (ic
->op
== CALL
|| ic
->op
== PCALL
))
1241 if (ic
->op
== SEND
|| (ic
->op
== IPUSH
&& ic
->parmPush
))
1249 /*-----------------------------------------------------------------*/
1250 /* operandLitValueUll - unsigned long long value of an operand */
1251 /*-----------------------------------------------------------------*/
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 /*-----------------------------------------------------------------*/
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 /*-----------------------------------------------------------------*/
1277 getBuiltinParms (iCode
* fic
, int *pcount
, operand
** parms
)
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
);
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
));
1302 /*-----------------------------------------------------------------*/
1303 /* operandOperation - performs operations on operands */
1304 /*-----------------------------------------------------------------*/
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
));
1315 assert (isOperandLiteral (right
));
1316 ret
= getSpec (operandType (right
));
1319 /* FIXME: most of these are not long long safe yet */
1323 retval
= operandFromValue (valCastLiteral (type
, operandLitValue (left
) + operandLitValue (right
), operandLitValueUll (left
) + operandLitValueUll (right
)), false);
1326 retval
= operandFromValue (valCastLiteral (type
, operandLitValue (left
) - operandLitValue (right
), operandLitValueUll (left
) - operandLitValueUll (right
)), false);
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
)
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
)
1385 /* all others go here: */
1386 retval
= operandFromValue (valCastLiteral (type
, operandLitValue (left
) * operandLitValue (right
), operandLitValueUll (left
) * operandLitValueUll (right
)), false);
1389 if (!IS_FLOAT (operandType (right
)) && (TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
)) == 0 && operandLitValueUll (right
) == 0)
1391 werror (E_DIVIDE_BY_ZERO
);
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
,
1402 operandLitValueUll (left
) /
1403 operandLitValueUll (right
)), false);
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);
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);
1416 retval
= operandFromValue (valCastLiteral (type
, operandLitValue (left
) / operandLitValue (right
), operandLitValueUll (left
) / operandLitValueUll (right
)), false);
1420 if ((TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
)) == 0 && operandLitValueUll (right
) == 0)
1422 werror (E_DIVIDE_BY_ZERO
);
1427 if (IS_UNSIGNED (type
))
1429 if (IS_LONGLONG (type
))
1430 retval
= operandFromValue (valCastLiteral (type
,
1432 operandLitValueUll (left
) %
1433 operandLitValueUll (right
)), false);
1435 retval
= operandFromLit ((TYPE_TARGET_ULONG
) double2ul (operandLitValue (left
)) % (TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
)));
1438 retval
= operandFromLit ((TYPE_TARGET_LONG
) operandLitValue (left
) % (TYPE_TARGET_LONG
) operandLitValue (right
));
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);
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);
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);
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
));
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
);
1496 retval
= operandFromLit (operandLitValue (left
) < operandLitValue (right
));
1499 retval
= operandFromLit (operandLitValue (left
) <= operandLitValue (right
));
1502 retval
= operandFromLit (operandLitValue (left
) != operandLitValue (right
));
1505 retval
= operandFromLit (operandLitValue (left
) > operandLitValue (right
));
1508 retval
= operandFromLit (operandLitValue (left
) >= operandLitValue (right
));
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);
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);
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);
1532 retval
= operandFromLit (operandLitValue (left
) && operandLitValue (right
));
1535 retval
= operandFromLit (operandLitValue (left
) || operandLitValue (right
));
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
)));
1545 retval
= operandFromLit (((TYPE_TARGET_ULONG
) double2ul (operandLitValue (left
)) >>
1546 (TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
))) & 1);
1549 retval
= operandFromLit (((TYPE_TARGET_ULONG
) double2ul (operandLitValue (left
)) >>
1550 (TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
)) & 0xFF));
1553 retval
= operandFromLit (((TYPE_TARGET_ULONG
) double2ul (operandLitValue (left
)) >>
1554 (TYPE_TARGET_ULONG
) double2ul (operandLitValue (right
)) & 0xFFFF));
1558 retval
= operandFromValue (valCastLiteral (type
, -1 * operandLitValue (left
), (-1ll) * operandLitValueUll (left
)), false);
1562 retval
= operandFromValue (valCastLiteral (type
, ~((TYPE_TARGET_ULONG
) double2ul (operandLitValue (left
))), ~((TYPE_TARGET_ULONGLONG
) operandLitValueUll (left
))), false);
1566 retval
= operandFromLit (!operandLitValue (left
));
1570 retval
= operandFromValue (valCastLiteral (type
, operandLitValue (left
), (TYPE_TARGET_ULONGLONG
) operandLitValueUll (left
)), false);
1574 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, " operandOperation invalid operator ");
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 */
1591 /* if either of them is null then false */
1592 if (!left
|| !right
)
1595 if (left
->type
!= right
->type
)
1598 if (IS_SYMOP (left
) && IS_SYMOP (right
))
1599 return left
->key
== right
->key
;
1601 /* if types are the same */
1605 return isSymbolEqual (left
->svt
.symOperand
, right
->svt
.symOperand
);
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
))));
1612 if (compareType (left
->svt
.typeOperand
, right
->svt
.typeOperand
, false) == 1)
1619 /*-------------------------------------------------------------------*/
1620 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1621 /*-------------------------------------------------------------------*/
1623 isiCodeEqual (iCode
* left
, iCode
* right
)
1625 /* if the same pointer */
1629 /* if either of them null */
1630 if (!left
|| !right
)
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
)))
1641 if (!isOperandEqual (IC_RIGHT (left
), IC_RIGHT (right
)))
1646 if (!isOperandEqual (IC_COND (left
), IC_COND (right
)))
1648 if (!isSymbolEqual (IC_TRUE (left
), IC_TRUE (right
)))
1650 if (!isSymbolEqual (IC_FALSE (left
), IC_FALSE (right
)))
1659 /*-----------------------------------------------------------------*/
1660 /* newiTempFromOp - create a temp Operand with same attributes */
1661 /*-----------------------------------------------------------------*/
1663 newiTempFromOp (operand
* 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
;
1683 /*-----------------------------------------------------------------*/
1684 /* operand from operand - creates an operand holder for the type */
1685 /*-----------------------------------------------------------------*/
1687 operandFromOperand (operand
* op
)
1693 nop
= newOperand ();
1694 nop
->type
= op
->type
;
1695 nop
->isaddr
= op
->isaddr
;
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
;
1707 nop
->svt
.symOperand
= op
->svt
.symOperand
;
1710 nop
->svt
.valOperand
= op
->svt
.valOperand
;
1713 nop
->svt
.typeOperand
= op
->svt
.typeOperand
;
1720 /*-----------------------------------------------------------------*/
1721 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1722 /*-----------------------------------------------------------------*/
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
);
1737 /*-----------------------------------------------------------------*/
1738 /* operandFromSymbol - creates an operand from a symbol */
1739 /*-----------------------------------------------------------------*/
1741 operandFromSymbol (symbol
*sym
, bool convert_sym_to_ptr
)
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
);
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
))
1760 op
->svt
.symOperand
= sym
;
1762 op
->isvolatile
= isOperandVolatile (op
, TRUE
);
1763 op
->isGlobal
= isOperandGlobal (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)
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
))
1803 op
->svt
.symOperand
= sym
;
1806 op
->isvolatile
= isOperandVolatile (op
, TRUE
);
1807 op
->isGlobal
= isOperandGlobal (op
);
1808 op
->isPtr
= IS_PTR (operandType (op
));
1809 op
->isParm
= sym
->_isparm
;
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
)));
1825 IC_RESULT (ic
) = newiTempOperand (sym
->type
, 0);
1826 if (IS_ARRAY (sym
->type
))
1828 IC_RESULT (ic
) = geniCodeArray2Ptr (IC_RESULT (ic
));
1832 IC_RESULT (ic
)->isaddr
= (!IS_AGGREGATE (sym
->type
));
1837 return IC_RESULT (ic
);
1840 /*-----------------------------------------------------------------*/
1841 /* operandFromValue - creates an operand from value */
1842 /*-----------------------------------------------------------------*/
1844 operandFromValue (value
*val
, bool convert_sym_to_ptr
)
1848 /* if this is a symbol then do the symbol thing */
1850 return operandFromSymbol (val
->sym
, convert_sym_to_ptr
);
1852 /* this is not a symbol */
1855 op
->svt
.valOperand
= val
;
1856 op
->isLiteral
= isOperandLiteral (op
);
1860 /*-----------------------------------------------------------------*/
1861 /* operandFromLink - operand from typeChain */
1862 /*-----------------------------------------------------------------*/
1864 operandFromLink (sym_link
* type
)
1868 /* operand from sym_link */
1874 op
->svt
.typeOperand
= copyLinkChain (type
);
1878 /*-----------------------------------------------------------------*/
1879 /* operandFromLit - makes an operand from a literal value */
1880 /*-----------------------------------------------------------------*/
1882 operandFromLit (double i
)
1884 return operandFromValue (valueFromLit (i
), false);
1887 /*-----------------------------------------------------------------*/
1888 /* operandFromAst - creates an operand from an ast */
1889 /*-----------------------------------------------------------------*/
1891 operandFromAst (ast
* tree
, int lvl
, bool convert_sym_to_ptr
)
1896 /* depending on type do */
1900 return ast2iCode (tree
, lvl
+ 1);
1904 return operandFromValue (tree
->opval
.val
, convert_sym_to_ptr
);
1908 return operandFromLink (tree
->opval
.lnk
);
1915 /* Just to keep the compiler happy */
1916 return (operand
*) 0;
1919 /*-----------------------------------------------------------------*/
1920 /* setOperandType - sets the operand's type to the given type */
1921 /*-----------------------------------------------------------------*/
1923 setOperandType (operand
* op
, sym_link
* type
)
1925 /* depending on the type of operand */
1929 op
->svt
.valOperand
->etype
= getSpec (op
->svt
.valOperand
->type
= copyLinkChain (type
));
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
;
1943 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "attempt to modify type of source");
1947 op
->svt
.typeOperand
= copyLinkChain (type
);
1952 /*-----------------------------------------------------------------*/
1953 /* Get size in byte of ptr need to access an array */
1954 /*-----------------------------------------------------------------*/
1956 getArraySizePtr (operand
* op
)
1958 sym_link
*ltype
= operandType (op
);
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
)))
1974 return (NEARPTRSIZE
);
1979 return (FARPTRSIZE
);
1981 if (GPTRSIZE
> FARPTRSIZE
)
1982 return (GPTRSIZE
- 1);
1984 return (FARPTRSIZE
);
1987 return (FARPTRSIZE
);
1990 return (FARPTRSIZE
);
1993 /*-----------------------------------------------------------------*/
1994 /* perform "usual unary conversions" */
1995 /*-----------------------------------------------------------------*/
1998 usualUnaryConversions (operand
* op
)
2000 if (IS_INTEGRAL (operandType (op
)))
2002 if (getSize (operandType (op
)) < (unsigned int) INTSIZE
)
2005 return geniCodeCast (INTTYPE
, op
, TRUE
);
2012 /*-----------------------------------------------------------------*/
2013 /* perform "usual binary conversions" */
2014 /*-----------------------------------------------------------------*/
2017 usualBinaryConversions (operand
** op1
, operand
** op2
, RESULT_TYPE resultType
, int op
)
2020 sym_link
*rtype
= operandType (*op2
);
2021 sym_link
*ltype
= operandType (*op1
);
2023 ctype
= computeType (ltype
, rtype
, resultType
, op
);
2030 if (IS_CHAR (getSpec (ltype
)) && IS_CHAR (getSpec (rtype
)))
2032 /* one byte operations: keep signedness for code generator */
2039 *op1
= geniCodeCast (ctype
, *op1
, true);
2045 *op1
= geniCodeCast (ctype
, *op1
, TRUE
);
2046 *op2
= geniCodeCast (ctype
, *op2
, TRUE
);
2051 /*-----------------------------------------------------------------*/
2052 /* geniCodeValueAtAddress - generate intermediate code for value */
2054 /*-----------------------------------------------------------------*/
2056 geniCodeRValue (operand
* op
, bool force
)
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 */
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
);
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
);
2088 ic
= newiCode (GET_VALUE_AT_ADDRESS
, op
, operandFromLit (0));
2089 if ((IS_PTR (type
) && op
->isaddr
&& force
) || IS_ARRAY (type
))
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); */
2101 return IC_RESULT (ic
);
2104 /*-----------------------------------------------------------------*/
2105 /* checkPtrQualifiers - check for lost pointer qualifiers */
2106 /*-----------------------------------------------------------------*/
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");
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");
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 /*-----------------------------------------------------------------*/
2129 geniCodeCast (sym_link
*type
, operand
*op
, bool implicit
)
2133 sym_link
*opetype
= getSpec (optype
= operandType (op
));
2136 /* one of them has size zero then error */
2137 if (IS_VOID (optype
))
2139 werror (E_CAST_ZERO
);
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;
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
;
2173 return IC_RESULT (ic
);
2176 /*-----------------------------------------------------------------*/
2177 /* geniCodeLabel - will create a Label */
2178 /*-----------------------------------------------------------------*/
2180 geniCodeLabel (symbol
* label
)
2184 ic
= newiCodeLabelGoto (LABEL
, label
);
2188 /*-----------------------------------------------------------------*/
2189 /* geniCodeGoto - will create a Goto */
2190 /*-----------------------------------------------------------------*/
2192 geniCodeGoto (symbol
* label
)
2196 ic
= newiCodeLabelGoto (GOTO
, label
);
2200 /*-----------------------------------------------------------------*/
2201 /* geniCodeMultiply - gen intermediate code for multiplication */
2202 /*-----------------------------------------------------------------*/
2204 geniCodeMultiply (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
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 */
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 */
2251 ic
= newiCode ('*', left
, right
); /* multiplication by support routine */
2256 ic
= newiCode ('*', left
, right
); /* normal multiplication */
2259 IC_RESULT (ic
) = newiTempOperand (resType
, 1);
2262 return IC_RESULT (ic
);
2266 geniCodeAdd (operand
*left
, operand
*right
, RESULT_TYPE resultType
, int lvl
);
2268 geniCodeLogic (operand
*left
, operand
*right
, int op
, ast
*tree
);
2270 geniCodeRightShift (operand
*left
, operand
*right
);
2272 /*-----------------------------------------------------------------*/
2273 /* geniCodeDivision - gen intermediate code for division */
2274 /*-----------------------------------------------------------------*/
2276 geniCodeDivision (operand
*left
, operand
*right
, RESULT_TYPE resultType
, bool ptrdiffdiv
)
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
))
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
);
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
));
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)
2327 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
2330 return IC_RESULT (ic
);
2333 /*-----------------------------------------------------------------*/
2334 /* geniCodeModulus - gen intermediate code for modulus */
2335 /*-----------------------------------------------------------------*/
2337 geniCodeModulus (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
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)
2355 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
2358 return IC_RESULT (ic
);
2361 /*-----------------------------------------------------------------*/
2362 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2363 /*-----------------------------------------------------------------*/
2365 geniCodePtrPtrSubtract (operand
* left
, operand
* right
)
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);
2378 ic
= newiCode ('-', left
, right
);
2380 IC_RESULT (ic
) = result
= newiTempOperand (newIntLink (), 1);
2384 if (IS_VOID (ltype
->next
) || IS_VOID (rtype
->next
))
2389 return geniCodeDivision (result
, operandFromLit (getSize (ltype
->next
)), FALSE
, true);
2392 /*-----------------------------------------------------------------*/
2393 /* geniCodeSubtract - generates code for subtraction */
2394 /*-----------------------------------------------------------------*/
2396 geniCodeSubtract (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
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
);
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
))
2435 return IC_RESULT (ic
);
2438 /*-----------------------------------------------------------------*/
2439 /* geniCodeAdd - generates iCode for addition */
2440 /*-----------------------------------------------------------------*/
2442 geniCodeAdd (operand
*left
, operand
*right
, RESULT_TYPE resultType
, int lvl
)
2446 unsigned int nBytes
;
2452 /* if the right side is LITERAL zero */
2453 /* return the left side */
2454 if (IS_LITERAL (retype
) && right
->isLiteral
&& !floatFromVal (valFromType (rtype
)))
2457 /* if left is literal zero return right */
2458 if (!IS_PTR (ltype
) && IS_LITERAL (letype
) && left
->isLiteral
&& !floatFromVal (valFromType (ltype
)))
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
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: */
2487 SPEC_USIGN (getSpec (operandType (right
))) = 1;
2490 if (ptrSize
> getSize (rtype
) && !IS_UNSIGNED (retype
))
2497 type
= newIntLink();
2501 type
= newLongLink();
2506 right
= geniCodeCast (type
, right
, TRUE
);
2509 resType
= copyLinkChain (ltype
);
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
);
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
))
2536 return IC_RESULT (ic
);
2539 /*-----------------------------------------------------------------*/
2540 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2541 /*-----------------------------------------------------------------*/
2543 aggrToPtr (sym_link
* type
, bool force
)
2548 if (IS_PTR (type
) && !force
)
2551 etype
= getSpec (type
);
2552 ptype
= newLink (DECLARATOR
);
2556 /* set the pointer depending on the storage class */
2557 DCL_TYPE (ptype
) = PTR_TYPE (SPEC_OCLS (etype
));
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 /*-----------------------------------------------------------------*/
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
;
2594 /*-----------------------------------------------------------------*/
2595 /* geniCodeArray - array access */
2596 /*-----------------------------------------------------------------*/
2598 geniCodeArray (operand
* left
, operand
* right
, int lvl
, bool noderef
)
2602 sym_link
*ltype
= operandType (left
);
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
;
2615 if (IS_PTR (ltype
->next
) && left
->isaddr
)
2617 left
= geniCodeRValue (left
, FALSE
);
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: */
2632 SPEC_USIGN (getSpec (operandType (right
))) = 1;
2633 /* we can check for limits here */
2634 /* already done in SDCCast.c
2635 if (isOperandLiteral (right) &&
2638 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2640 werror (W_IDX_OUT_OF_BOUNDS,
2641 (int) operandLitValue (right) / getSize (ltype->next),
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;
2658 return IC_RESULT (ic
);
2661 /*-----------------------------------------------------------------*/
2662 /* geniCodeStruct - generates intermediate code for structures */
2663 /*-----------------------------------------------------------------*/
2665 geniCodeStruct (operand
* left
, operand
* right
, bool islval
)
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
));
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
));
2706 return (islval
? IC_RESULT (ic
) : geniCodeRValue (IC_RESULT (ic
), TRUE
));
2709 /*-----------------------------------------------------------------*/
2710 /* geniCodePostInc - generate int code for Post increment */
2711 /*-----------------------------------------------------------------*/
2713 geniCodePostInc (operand
* op
)
2717 sym_link
*optype
= operandType (op
);
2719 operand
*rv
= (IS_ITEMP (op
) ? geniCodeRValue (op
, (!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
) : op
);
2720 sym_link
*rvtype
= operandType (rv
);
2722 operand
*srcOp
= rv
;
2724 /* if this is not an address we have trouble */
2727 werror (E_LVALUE_REQUIRED
, "++");
2731 rOp
= newiTempOperand (rvtype
, 0);
2732 OP_SYMBOL (rOp
)->noSpilLoc
= 1;
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 */
2742 if (isOperandVolatile (rv
, FALSE
))
2745 size
= (IS_PTR (rvtype
) ? getSize (rvtype
->next
) : 1);
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));
2755 ic
= newiCode ('+', srcOp
, operandFromLit (size
));
2757 IC_RESULT (ic
) = result
= newiTempOperand (rvtype
, 0);
2760 geniCodeAssign (op
, result
, 0, 0);
2766 /*-----------------------------------------------------------------*/
2767 /* geniCodePreInc - generate code for preIncrement */
2768 /*-----------------------------------------------------------------*/
2770 geniCodePreInc (operand
* op
, bool lvalue
)
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
);
2781 werror (E_LVALUE_REQUIRED
, "++");
2785 size
= (IS_PTR (roptype
) ? getSize (roptype
->next
) : 1);
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));
2795 ic
= newiCode ('+', rop
, operandFromLit (size
));
2796 IC_RESULT (ic
) = result
= newiTempOperand (roptype
, 0);
2799 (void) geniCodeAssign (op
, result
, 0, 0);
2800 if (lvalue
|| (IS_TRUE_SYMOP (op
) && !isOperandVolatile (op
, FALSE
)) || IS_BITVAR (optype
))
2806 /*-----------------------------------------------------------------*/
2807 /* geniCodePostDec - generates code for Post decrement */
2808 /*-----------------------------------------------------------------*/
2810 geniCodePostDec (operand
* op
)
2814 sym_link
*optype
= operandType (op
);
2816 operand
*rv
= (IS_ITEMP (op
) ? geniCodeRValue (op
, ((!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
)) : op
);
2817 sym_link
*rvtype
= operandType (rv
);
2819 operand
*srcOp
= rv
;
2821 /* if this is not an address we have trouble */
2824 werror (E_LVALUE_REQUIRED
, "--");
2828 rOp
= newiTempOperand (rvtype
, 0);
2829 OP_SYMBOL (rOp
)->noSpilLoc
= 1;
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 */
2839 if (isOperandVolatile (rv
, FALSE
))
2842 size
= (IS_PTR (rvtype
) ? getSize (rvtype
->next
) : 1);
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);
2852 ic
= newiCode ('-', srcOp
, operandFromLit (size
));
2854 IC_RESULT (ic
) = result
= newiTempOperand (rvtype
, 0);
2857 geniCodeAssign (op
, result
, 0, 0);
2863 /*-----------------------------------------------------------------*/
2864 /* geniCodePreDec - generate code for pre decrement */
2865 /*-----------------------------------------------------------------*/
2867 geniCodePreDec (operand
* op
, bool lvalue
)
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
);
2878 werror (E_LVALUE_REQUIRED
, "--");
2882 size
= (IS_PTR (roptype
) ? getSize (roptype
->next
) : 1);
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);
2892 ic
= newiCode ('-', rop
, operandFromLit (size
));
2893 IC_RESULT (ic
) = result
= newiTempOperand (roptype
, 0);
2896 (void) geniCodeAssign (op
, result
, 0, 0);
2897 if (lvalue
|| (IS_TRUE_SYMOP (op
) && !isOperandVolatile (op
, FALSE
)) || IS_BITVAR (optype
))
2904 /*-----------------------------------------------------------------*/
2905 /* geniCodeBitwise - gen int code for bitWise operators */
2906 /*-----------------------------------------------------------------*/
2908 geniCodeBitwise (operand
* left
, operand
* right
, int oper
, sym_link
* resType
)
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);
2923 return IC_RESULT (ic
);
2926 /*-----------------------------------------------------------------*/
2927 /* geniCodeAddressOf - gens icode for '&' address of operator */
2928 /*-----------------------------------------------------------------*/
2930 geniCodeAddressOf (operand
* op
)
2934 sym_link
*optype
= operandType (op
);
2935 sym_link
*opetype
= getSpec (optype
);
2937 if (IS_ITEMP (op
) && IS_PTR (optype
))
2939 op
= operandFromOperand (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,"&"); */
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 */
2961 setOperandType (op
, p
);
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;
2971 return IC_RESULT (ic
);
2974 /*-----------------------------------------------------------------*/
2975 /* setOClass - sets the output class depending on the pointer type */
2976 /*-----------------------------------------------------------------*/
2978 setOClass (sym_link
* ptr
, sym_link
* spec
)
2980 switch (DCL_TYPE (ptr
))
2983 SPEC_OCLS (spec
) = data
;
2987 SPEC_OCLS (spec
) = generic
;
2991 SPEC_OCLS (spec
) = xdata
;
2995 SPEC_OCLS (spec
) = code
;
2999 SPEC_OCLS (spec
) = idata
;
3003 SPEC_OCLS (spec
) = xstack
;
3007 SPEC_OCLS (spec
) = eeprom
;
3015 /*-----------------------------------------------------------------*/
3016 /* geniCodeDerefPtr - dereference pointer with '*' */
3017 /*-----------------------------------------------------------------*/
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
))
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. */
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
;
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
));
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;
3083 SPEC_ADDRSPACE (rtype
) = 0;
3084 SPEC_VOLATILE (rtype
) = 0;
3086 setOperandType (op
, rtype
);
3091 /*-----------------------------------------------------------------*/
3092 /* geniCodeUnaryMinus - does a unary minus of the operand */
3093 /*-----------------------------------------------------------------*/
3095 geniCodeUnaryMinus (operand
* op
)
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);
3106 return IC_RESULT (ic
);
3109 /*-----------------------------------------------------------------*/
3110 /* geniCodeLeftShift - gen i code for left shift */
3111 /*-----------------------------------------------------------------*/
3113 geniCodeLeftShift (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
3118 resType
= usualBinaryConversions (&left
, &right
, resultType
, LEFT_OP
);
3119 ic
= newiCode(LEFT_OP
, left
, right
);
3120 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
3122 return IC_RESULT (ic
);
3125 /*-----------------------------------------------------------------*/
3126 /* geniCodeRightShift - gen i code for right shift */
3127 /*-----------------------------------------------------------------*/
3129 geniCodeRightShift (operand
* left
, operand
* right
)
3133 ic
= newiCode (RIGHT_OP
, left
, right
);
3134 IC_RESULT (ic
) = newiTempOperand (operandType (left
), 0);
3136 return IC_RESULT (ic
);
3139 /*-----------------------------------------------------------------*/
3140 /* geniCodeLogic- logic code */
3141 /*-----------------------------------------------------------------*/
3143 geniCodeLogic (operand
* left
, operand
* right
, int op
, ast
* tree
)
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
);
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);
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 */
3180 if (((ic
->op
== CAST
) || (ic
->op
== '=')) && isOperandEqual (left
, IC_RESULT (ic
)))
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 */
3198 if (((ic
->op
== CAST
) || (ic
->op
== '=')) && isOperandEqual (right
, IC_RESULT (ic
)))
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
3221 if (IS_FLOAT (ctype
) && op
!= EQ_OP
&& op
!= NE_OP
&& op
!= AND_OP
&& op
!= OR_OP
)
3224 /* if comparing a fixed type use support functions */
3225 if (IS_FIXED (ctype
))
3229 return IC_RESULT (ic
);
3232 /*-----------------------------------------------------------------*/
3233 /* geniCodeLogicAndOr - && || operations */
3234 /*-----------------------------------------------------------------*/
3236 geniCodeLogicAndOr (ast
* tree
, int lvl
)
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:
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
);
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
);
3271 ic
= newiCodeCondition (op
, trueLabel
, NULL
);
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
);
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
);
3299 /*-----------------------------------------------------------------*/
3300 /* geniCodeUnary - for a generic unary operation */
3301 /*-----------------------------------------------------------------*/
3303 geniCodeUnary (operand
* op
, int oper
, sym_link
* resType
)
3305 iCode
*ic
= newiCode (oper
, op
, NULL
);
3307 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
3309 return IC_RESULT (ic
);
3312 /*-----------------------------------------------------------------*/
3313 /* geniCodeBinary - for a generic binary operation */
3314 /*-----------------------------------------------------------------*/
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);
3322 return IC_RESULT (ic
);
3325 /*-----------------------------------------------------------------*/
3326 /* geniCodeConditional - geniCode for '?' ':' operation */
3327 /*-----------------------------------------------------------------*/
3329 geniCodeConditional (ast
* tree
, int lvl
)
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
);
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
);
3363 /*-----------------------------------------------------------------*/
3364 /* checkTypes - check types for assignment */
3365 /*-----------------------------------------------------------------*/
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)
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
);
3405 DCL_PTR_VOLATILE (ltype
) = 0;
3407 SPEC_VOLATILE (ltype
) = 0;
3409 right
= geniCodeCast (ltype
, right
, TRUE
);
3411 checkPtrQualifiers (ltype
, rtype
, !right
->isConstElimnated
);
3415 /*-----------------------------------------------------------------*/
3416 /* geniCodeAssign - generate code for assignment */
3417 /*-----------------------------------------------------------------*/
3419 geniCodeAssign (operand
* left
, operand
* right
, int nosupdate
, int strictLval
)
3424 if (!left
->isaddr
&& (!IS_ITEMP (left
) || strictLval
))
3426 werror (E_LVALUE_REQUIRED
, "assignment");
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
))
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
;
3455 ic
= newiCode ('=', NULL
, right
);
3456 IC_RESULT (ic
) = left
;
3459 /* if left isgptr flag is set then support
3460 routine will be required */
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
))
3474 /*-----------------------------------------------------------------*/
3475 /* geniCodeDummyRead - generate code for dummy read */
3476 /*-----------------------------------------------------------------*/
3478 geniCodeDummyRead (operand
* op
)
3481 sym_link
*type
= operandType (op
);
3483 if (!IS_VOLATILE (type
))
3486 ic
= newiCode (DUMMY_READ_VOLATILE
, NULL
, op
);
3492 /*-----------------------------------------------------------------*/
3493 /* geniCodeSEParms - generate code for side effecting fcalls */
3494 /*-----------------------------------------------------------------*/
3496 geniCodeSEParms (ast
*parms
, int lvl
)
3501 if (IS_AST_PARAM (parms
))
3503 geniCodeSEParms (parms
->left
, lvl
);
3504 geniCodeSEParms (parms
->right
, lvl
);
3508 /* hack don't like this but too lazy to think of
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 /*-----------------------------------------------------------------*/
3528 geniCodeParms (ast
* parms
, value
* argVals
, int *iArg
, int *stack
, sym_link
* ftype
, int lvl
, iCode
*iic_start
)
3531 iCode
*castic_start
= 0;
3532 iCode
*castic_end
= 0;
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
);
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
);
3564 bool is_structparm
= IS_STRUCT (parms
->ftype
); // struct parameter handling is hackish.
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
);
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
);
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
);
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.
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
;
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
;
3647 cic
->next
= iic_end
;
3649 iic_end
->prev
= cic
;
3650 else if (iic_start
== iCodeChainEnd
)
3651 iCodeChainEnd
= cic
;
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);
3664 if (argVals
&& (*iArg
>= 0))
3665 pval
= checkTypes (operandFromValue (argVals
, false), pval
);
3668 ic
= newiCode (IPUSH_VALUE_AT_ADDRESS
, pval
, operandFromLit (0));
3670 ic
= newiCode (IPUSH
, pval
, NULL
);
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.
3677 if (TARGET_PDK_LIKE
&& getSize (parmtype
) % 2) // So does pdk due to stack alignment requirements.
3685 assert (argVals
!= NULL
);
3686 argVals
= argVals
->next
;
3692 /*-----------------------------------------------------------------*/
3693 /* geniCodeCall - generates temp code for calling */
3694 /*-----------------------------------------------------------------*/
3696 geniCodeCall (operand
* left
, ast
* parms
, int lvl
)
3699 sym_link
*type
, *etype
;
3704 if (IS_ARRAY (operandType (left
)))
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;
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"))
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
))
3748 //count expected arguments except varargs
3749 for (argVals
= FUNC_ARGS (ftype
); argVals
; argVals
= argVals
->next
)
3751 //count actual parameters including varargs
3752 for (parm
= parms
; parm
&& parm
->type
== EX_OP
&& parm
->opval
.op
== PARAM
; parm
= parm
->right
)
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
);
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
);
3779 ic
= newiCode (CALL
, left
, NULL
);
3782 type
= copyLinkChain (ftype
->next
);
3783 etype
= getSpec (type
);
3784 SPEC_EXTR (etype
) = 0;
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
);
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 /*-----------------------------------------------------------------*/
3817 geniCodeReceive (value
* args
, operand
* func
)
3819 unsigned char paramByteCounter
= 0;
3821 /* for all arguments that are passed in registers */
3824 if (IS_REGPARM (args
->etype
))
3826 operand
*opr
= operandFromValue (args
, true);
3828 symbol
*sym
= OP_SYMBOL (opr
);
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
)))
3842 opl
= newiTempOperand (args
->type
, 0);
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
);
3877 /*-----------------------------------------------------------------*/
3878 /* geniCodeFunctionBody - create the function body */
3879 /*-----------------------------------------------------------------*/
3881 geniCodeFunctionBody (ast
* tree
, int lvl
)
3887 short functionBlock
;
3889 /* reset the auto generation */
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
;
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
;
3935 /*-----------------------------------------------------------------*/
3936 /* geniCodeReturn - gen icode for 'return' statement */
3937 /*-----------------------------------------------------------------*/
3939 geniCodeReturn (operand
* op
)
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 */
3953 op
= geniCodeRValue (op
, FALSE
);
3955 ic
= newiCode (RETURN
, op
, NULL
);
3959 /*-----------------------------------------------------------------*/
3960 /* geniCodeIfx - generates code for extended if statement */
3961 /*-----------------------------------------------------------------*/
3963 geniCodeIfx (ast
* tree
, int lvl
)
3966 operand
*condition
= ast2iCode (tree
->left
, lvl
+ 1);
3969 /* if condition is null then exit */
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
);
3988 if (tree
->falseLabel
)
3989 geniCodeGoto (tree
->falseLabel
);
3994 if (tree
->trueLabel
)
3996 ic
= newiCodeCondition (condition
, tree
->trueLabel
, NULL
);
3999 if (tree
->falseLabel
)
4000 geniCodeGoto (tree
->falseLabel
);
4004 ic
= newiCodeCondition (condition
, NULL
, tree
->falseLabel
);
4009 if (tree
->right
&& tree
->right
->type
== EX_VALUE
)
4010 geniCodeDummyRead (ast2iCode (tree
->right
, lvl
+ 1));
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;
4023 value
*vch
, *maxVal
;
4027 sym_link
*cetype
= getSpec (operandType (cond
));
4028 int sizeofMinCost
, sizeofZeroMinCost
, sizeofMaxCost
;
4029 int sizeofMatchJump
, sizeofJumpTable
;
4033 if (!tree
|| !caseVals
)
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
);
4049 max
= (int) ulFromVal (vch
);
4054 /* Exit if the range is too large to handle with a jump table. */
4055 if (1 + max
- min
> port
->jumptableCost
.maxCount
)
4058 switch (getSize (operandType (cond
)))
4073 /* Compute the size cost of the range check and subtraction. */
4075 sizeofZeroMinCost
= 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
];
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
)
4096 if (IS_UNSIGNED (cetype
))
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
)
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
: "");
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. */
4133 t
= (int) ulFromVal (vch
);
4134 for (i
= min
; i
<= max
; 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
);
4146 t
= (int) ulFromVal (vch
);
4150 /* Implicit case: use the default label. */
4151 addSet (&labels
, falseLabel
);
4155 /* first we rule out the boundary conditions */
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
);
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
);
4182 /* if the min is not zero then we now make it zero */
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
;
4198 /*-----------------------------------------------------------------*/
4199 /* geniCodeSwitch - changes a switch to a if statement */
4200 /*-----------------------------------------------------------------*/
4202 geniCodeSwitch (ast
* tree
, int lvl
)
4205 operand
*cond
= geniCodeRValue (ast2iCode (tree
->left
, lvl
+ 1), FALSE
);
4206 value
*caseVals
= tree
->values
.switchVals
.swVals
;
4207 symbol
*trueLabel
, *falseLabel
;
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
));
4219 caseVal
= (int) ulFromVal (caseVals
);
4220 if (caseVal
== switchVal
)
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
);
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
))
4245 newcond
= newiTempOperand (operandType (cond
), TRUE
);
4246 newcond
->isvolatile
= 0;
4247 ic
= newiCode ('=', NULL
, cond
);
4248 IC_RESULT (ic
) = 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 */
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
);
4270 caseVals
= caseVals
->next
;
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
: "");
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
);
4292 ast2iCode (tree
->right
, lvl
+ 1);
4295 /*-----------------------------------------------------------------*/
4296 /* geniCodeInline - intermediate code for inline assembler */
4297 /*-----------------------------------------------------------------*/
4299 geniCodeInline (ast
* tree
)
4303 ic
= newiCode (INLINEASM
, NULL
, NULL
);
4304 IC_INLINE (ic
) = tree
->values
.inlineasm
;
4308 /*-----------------------------------------------------------------*/
4309 /* geniCodeArrayInit - intermediate code for array initializer */
4310 /*-----------------------------------------------------------------*/
4312 geniCodeArrayInit (ast
* tree
, operand
* array
)
4316 if (!getenv ("TRY_THE_NEW_INITIALIZER"))
4318 ic
= newiCode (ARRAYINIT
, array
, NULL
);
4319 IC_ARRAYILIST (ic
) = tree
->values
.constlist
;
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
);
4332 /*-----------------------------------------------------------------*/
4333 /* geniCodeCritical - intermediate code for a critical statement */
4334 /*-----------------------------------------------------------------*/
4336 geniCodeCritical (ast
* tree
, int lvl
)
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 */
4358 ic
= newiCode (CRITICAL
, NULL
, NULL
);
4359 IC_RESULT (ic
) = op
;
4362 /* Generate the critical code sequence */
4363 if (tree
->left
&& tree
->left
->type
== EX_VALUE
)
4364 geniCodeDummyRead (ast2iCode (tree
->left
, lvl
+ 1));
4366 ast2iCode (tree
->left
, lvl
+ 1);
4368 /* Generate a restore of the original interrupt state */
4369 ic
= newiCode (ENDCRITICAL
, NULL
, op
);
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
4386 /*-----------------------------------------------------------------*/
4387 /* addLvaluereq - add a flag for lvalreq for current ast level */
4388 /*-----------------------------------------------------------------*/
4390 addLvaluereq (int lvl
)
4392 lvalItem
*lpItem
= (lvalItem
*) Safe_alloc (sizeof (lvalItem
));
4395 addSetHead (&lvaluereqSet
, lpItem
);
4398 /*-----------------------------------------------------------------*/
4399 /* delLvaluereq - del a flag for lvalreq for current ast level */
4400 /*-----------------------------------------------------------------*/
4404 lvalItem
*lpItem
= getSet (&lvaluereqSet
);
4409 /*-----------------------------------------------------------------*/
4410 /* clearLvaluereq - clear lvalreq flag */
4411 /*-----------------------------------------------------------------*/
4415 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4420 /*-----------------------------------------------------------------*/
4421 /* getLvaluereq - get the last lvalreq level */
4422 /*-----------------------------------------------------------------*/
4427 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4433 /*-----------------------------------------------------------------*/
4434 /* isLvaluereq - is lvalreq valid for this level ? */
4435 /*-----------------------------------------------------------------*/
4437 isLvaluereq (int lvl
)
4439 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4441 return ((lpItem
->req
) && (lvl
<= (lpItem
->lvl
+ 1)));
4445 /*-----------------------------------------------------------------*/
4446 /* ast2iCode - creates an icodeList from an ast */
4447 /*-----------------------------------------------------------------*/
4449 ast2iCode (ast
* tree
, int lvl
)
4451 operand
*left
= NULL
;
4452 operand
*right
= NULL
;
4456 /* set the global variables for filename & line number */
4458 filename
= tree
->filename
;
4460 lineno
= tree
->lineno
;
4462 block
= tree
->block
;
4464 scopeLevel
= tree
->level
;
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
;
4480 if (tree
->left
&& tree
->left
->type
== EX_VALUE
)
4481 geniCodeDummyRead (ast2iCode (tree
->left
, lvl
+ 1));
4483 ast2iCode (tree
->left
, lvl
+ 1);
4484 if (tree
->right
&& tree
->right
->type
== EX_VALUE
)
4485 geniCodeDummyRead (ast2iCode (tree
->right
, lvl
+ 1));
4487 ast2iCode (tree
->right
, lvl
+ 1);
4488 inlinedActive
= oldInlinedActive
;
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
))
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
)))
4512 left
= operandFromAst (tree
->left
, lvl
, true);
4514 if (IS_DEREF_OP (tree
) && IS_DEREF_OP (tree
->left
))
4515 left
= geniCodeRValue (left
, TRUE
);
4519 left
= operandFromAst (tree
->left
, lvl
, true);
4521 if (tree
->opval
.op
== INC_OP
|| tree
->opval
.op
== DEC_OP
)
4524 right
= operandFromAst (tree
->right
, lvl
, true);
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
);
4551 left
= geniCodeRValue (left
, FALSE
);
4553 return geniCodeStruct (left
, right
, tree
->lvalue
);
4555 case PTR_OP
: /* structure pointer dereference */
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 */
4568 return geniCodePostInc (left
);
4570 return geniCodePreInc (right
, tree
->lvalue
);
4572 case DEC_OP
: /* decrement operator */
4574 return geniCodePostDec (left
);
4576 return geniCodePreDec (right
, tree
->lvalue
);
4578 case '&': /* bitwise and or address of operator */
4580 { /* this is a bitwise operator */
4581 left
= geniCodeRValue (left
, FALSE
);
4582 right
= geniCodeRValue (right
, FALSE
);
4583 return geniCodeBitwise (left
, right
, BITWISEAND
, tree
->ftype
);
4586 return geniCodeAddressOf (left
);
4588 case '|': /* bitwise or & xor */
4590 return geniCodeBitwise (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4593 return geniCodeDivision (geniCodeRValue (left
, FALSE
),
4594 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), false);
4597 return geniCodeModulus (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4600 return geniCodeMultiply (geniCodeRValue (left
, FALSE
),
4601 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4603 return geniCodeDerefPtr (geniCodeRValue (left
, FALSE
), lvl
);
4607 return geniCodeSubtract (geniCodeRValue (left
, FALSE
),
4608 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4610 return geniCodeUnaryMinus (geniCodeRValue (left
, FALSE
));
4614 return geniCodeAdd (geniCodeRValue (left
, FALSE
),
4615 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), lvl
);
4617 return geniCodeRValue (left
, FALSE
); /* unary '+' has no meaning */
4620 return geniCodeLeftShift (geniCodeRValue (left
, FALSE
),
4621 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4624 return geniCodeRightShift (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
));
4626 #if 0 // this indeed needs a second thought
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
4641 #else // bug #604575, is it a bug ????
4642 return geniCodeCast (operandType (left
), geniCodeRValue (right
, FALSE
), FALSE
);
4646 return geniCodeUnary (geniCodeRValue (left
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4650 operand
*op
= geniCodeUnary (geniCodeRValue (left
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4655 operand
*op
= geniCodeBinary (geniCodeRValue (left
, false),
4656 geniCodeRValue (right
, false),
4657 tree
->opval
.op
, tree
->ftype
);
4662 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4663 geniCodeRValue (right
, FALSE
),
4664 tree
->opval
.op
, tree
->ftype
);
4669 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4670 geniCodeRValue (right
, FALSE
),
4671 tree
->opval
.op
, tree
->ftype
);
4672 setOperandType (op
, UCHARTYPE
);
4677 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4678 geniCodeRValue (right
, FALSE
),
4679 tree
->opval
.op
, tree
->ftype
);
4680 setOperandType (op
, UINTTYPE
);
4685 return geniCodeLogicAndOr (tree
, lvl
);
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),
4700 operand
*leftOp
, *rightOp
;
4702 leftOp
= geniCodeRValue (left
, FALSE
);
4703 rightOp
= geniCodeRValue (right
, FALSE
);
4705 return geniCodeLogic (leftOp
, rightOp
, tree
->opval
.op
, tree
);
4708 return geniCodeConditional (tree
, lvl
);
4711 return operandFromLit (getSize (tree
->right
->ftype
));
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
);
4720 right
= geniCodeRValue (right
, FALSE
);
4721 return geniCodeAssign (left
, right
, 0, 1);
4725 geniCodeAssign (left
,
4726 geniCodeMultiply (geniCodeRValue (operandFromOperand (left
),
4728 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
4732 geniCodeAssign (left
,
4733 geniCodeDivision (geniCodeRValue (operandFromOperand (left
), FALSE
),
4734 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), false), 0, 1);
4737 geniCodeAssign (left
,
4738 geniCodeModulus (geniCodeRValue (operandFromOperand (left
),
4740 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
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
);
4748 right
= geniCodeRValue (right
, FALSE
);
4751 return geniCodeAssign (left
,
4752 geniCodeAdd (geniCodeRValue (operandFromOperand (left
),
4753 FALSE
), right
, getResultTypeFromType (tree
->ftype
), lvl
), 0, 1);
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
);
4765 right
= geniCodeRValue (right
, FALSE
);
4768 geniCodeAssign (left
,
4769 geniCodeSubtract (geniCodeRValue (operandFromOperand (left
),
4770 FALSE
), right
, getResultTypeFromType (tree
->ftype
)), 0, 1);
4774 geniCodeAssign (left
,
4775 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left
), FALSE
),
4776 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
4779 geniCodeAssign (left
,
4780 geniCodeRightShift (geniCodeRValue (operandFromOperand (left
), FALSE
),
4781 geniCodeRValue (right
, FALSE
)), 0, 1);
4784 geniCodeAssign (left
,
4785 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
),
4787 geniCodeRValue (right
, FALSE
), BITWISEAND
, operandType (left
)), 0, 1);
4790 geniCodeAssign (left
,
4791 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
),
4792 FALSE
), geniCodeRValue (right
, FALSE
), '^', operandType (left
)), 0, 1);
4795 geniCodeAssign (left
,
4796 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
), FALSE
),
4797 geniCodeRValue (right
, FALSE
), '|', operandType (left
)), 0, 1);
4799 return geniCodeRValue (right
, FALSE
);
4802 return geniCodeCall (ast2iCode (tree
->left
, lvl
+ 1), tree
->right
, lvl
);
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));
4812 return ast2iCode (tree
->right
, lvl
+ 1);
4815 geniCodeGoto (OP_SYMBOL (ast2iCode (tree
->left
, lvl
+ 1)));
4816 return ast2iCode (tree
->right
, lvl
+ 1);
4819 geniCodeFunctionBody (tree
, lvl
);
4823 geniCodeReturn (right
);
4827 geniCodeIfx (tree
, lvl
);
4831 geniCodeSwitch (tree
, lvl
);
4835 geniCodeInline (tree
);
4839 geniCodeArrayInit (tree
, ast2iCode (tree
->left
, lvl
+ 1));
4843 geniCodeCritical (tree
, lvl
);
4849 /*-----------------------------------------------------------------*/
4850 /* iCodeFromAst - given an ast will convert it to iCode */
4851 /*-----------------------------------------------------------------*/
4853 iCodeFromAst (ast
* tree
)
4855 returnLabel
= newiTempLabel ("_return");
4856 entryLabel
= newiTempLabel ("_entry");
4858 ast2iCode (tree
, 0);
4859 return (iCodeChain
);
4863 opTypeToStr (OPTYPE op
)
4874 return "undefined type";
4879 validateOpType (operand
*op
, const char *macro
, const char *args
, OPTYPE type
, const char *file
, unsigned line
)
4881 if (op
&& op
->type
== type
)
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.
4893 validateOpTypeConst (const operand
*op
, const char *macro
, const char *args
, OPTYPE type
, const char *file
, unsigned line
)
4895 if (op
&& op
->type
== type
)
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.