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_ULONGLONG
) ullFromVal (OP_VALUE (right
)))) > 0))
2295 ic
= newiCode (RIGHT_OP
, left
, operandFromLit (p2
)); /* right shift */
2297 /* if the right is a literal & power of 2
2298 and left is signed then make it a conditional addition
2299 followed by right shift */
2300 else if (IS_LITERAL (retype
) &&
2301 !IS_FLOAT (letype
) &&
2302 !IS_FIXED (letype
) && !IS_UNSIGNED (letype
) &&
2303 floatFromVal (OP_VALUE (right
)) >= 0 &&
2304 ((p2
= powof2 ((TYPE_TARGET_ULONGLONG
) ullFromVal (OP_VALUE (right
)))) > 0) &&
2305 (TARGET_Z80_LIKE
|| TARGET_HC08_LIKE
|| TARGET_MOS6502_LIKE
))
2308 symbol
*label
= newiTempLabel (NULL
);
2310 tmp
= newiTempOperand (ltype
, 0);
2311 geniCodeAssign (tmp
, left
, 0, 0);
2313 ic
= newiCodeCondition (geniCodeLogic (tmp
, operandFromLit (0), '<', 0), 0, label
);
2316 geniCodeAssign (tmp
, geniCodeAdd (tmp
, operandFromLit ((1 << p2
) - 1), 0, 0), 0, 0);
2317 geniCodeLabel (label
);
2318 return (geniCodeCast (resType
, geniCodeRightShift (tmp
, operandFromLit (p2
)), TRUE
));
2323 ic
= newiCode ('/', left
, right
); /* normal division */
2324 /* if the size left or right > 1 then support routine */
2325 if (getSize (ltype
) > 1 || getSize (rtype
) > 1)
2328 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
2331 return IC_RESULT (ic
);
2334 /*-----------------------------------------------------------------*/
2335 /* geniCodeModulus - gen intermediate code for modulus */
2336 /*-----------------------------------------------------------------*/
2338 geniCodeModulus (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
2344 /* if they are both literal then we know the result */
2345 if (IS_LITERAL (letype
) && IS_LITERAL (retype
))
2346 return operandFromValue (valMod (OP_VALUE (left
), OP_VALUE (right
), true), false);
2348 resType
= usualBinaryConversions (&left
, &right
, resultType
, '%');
2350 /* now they are the same size */
2351 ic
= newiCode ('%', left
, right
);
2353 /* if the size left or right > 1 then support routine */
2354 if (getSize (ltype
) > 1 || getSize (rtype
) > 1)
2356 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
2359 return IC_RESULT (ic
);
2362 /*-----------------------------------------------------------------*/
2363 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
2364 /*-----------------------------------------------------------------*/
2366 geniCodePtrPtrSubtract (operand
* left
, operand
* right
)
2372 /* if they are both literals then */
2373 if (IS_LITERAL (letype
) && IS_LITERAL (retype
))
2375 result
= operandFromValue (valMinus (OP_VALUE (left
), OP_VALUE (right
), true), true);
2379 ic
= newiCode ('-', left
, right
);
2381 IC_RESULT (ic
) = result
= newiTempOperand (newIntLink (), 1);
2385 if (IS_VOID (ltype
->next
) || IS_VOID (rtype
->next
))
2390 return geniCodeDivision (result
, operandFromLit (getSize (ltype
->next
)), FALSE
, true);
2393 /*-----------------------------------------------------------------*/
2394 /* geniCodeSubtract - generates code for subtraction */
2395 /*-----------------------------------------------------------------*/
2397 geniCodeSubtract (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
2404 /* if they are both pointers then */
2405 if ((IS_PTR (ltype
) || IS_ARRAY (ltype
)) && (IS_PTR (rtype
) || IS_ARRAY (rtype
)))
2406 return geniCodePtrPtrSubtract (left
, right
);
2408 /* if they are both literal then we know the result */
2409 if (IS_LITERAL (letype
) && IS_LITERAL (retype
) && left
->isLiteral
&& right
->isLiteral
)
2410 return operandFromValue (valMinus (OP_VALUE (left
), OP_VALUE (right
), true), false);
2412 /* if left is an array or pointer */
2413 if (IS_PTR (ltype
) || IS_ARRAY (ltype
))
2415 isarray
= left
->isaddr
;
2416 right
= geniCodeMultiply (right
,
2417 operandFromLit (getSize (ltype
->next
)),
2418 (getArraySizePtr (left
) >= INTSIZE
) ? RESULT_TYPE_INT
: RESULT_TYPE_CHAR
);
2419 resType
= copyLinkChain (IS_ARRAY (ltype
) ? ltype
->next
: ltype
);
2422 { /* make them the same size */
2423 resType
= usualBinaryConversions (&left
, &right
, resultType
, '-');
2426 ic
= newiCode ('-', left
, right
);
2428 IC_RESULT (ic
) = newiTempOperand (resType
, 1);
2429 IC_RESULT (ic
)->isaddr
= (isarray
? 1 : 0);
2431 /* if left or right is a float */
2432 if (IS_FLOAT (ltype
) || IS_FLOAT (rtype
) || IS_FIXED (ltype
) || IS_FIXED (rtype
))
2436 return IC_RESULT (ic
);
2439 /*-----------------------------------------------------------------*/
2440 /* geniCodeAdd - generates iCode for addition */
2441 /*-----------------------------------------------------------------*/
2443 geniCodeAdd (operand
*left
, operand
*right
, RESULT_TYPE resultType
, int lvl
)
2447 unsigned int nBytes
;
2453 /* if the right side is LITERAL zero */
2454 /* return the left side */
2455 if (IS_LITERAL (retype
) && right
->isLiteral
&& !floatFromVal (valFromType (rtype
)))
2458 /* if left is literal zero return right */
2459 if (!IS_PTR (ltype
) && IS_LITERAL (letype
) && left
->isLiteral
&& !floatFromVal (valFromType (ltype
)))
2462 /* if left is a pointer then size */
2463 if (IS_PTR (ltype
) || IS_ARRAY (ltype
))
2465 unsigned int ptrSize
;
2466 isarray
= left
->isaddr
;
2467 nBytes
= getSize (ltype
->next
);
2468 ptrSize
= getArraySizePtr (left
); // works for both arrays and pointers
2470 if (nBytes
== 0 && !IS_VOID (ltype
->next
))
2471 werror (E_UNKNOWN_SIZE
, IS_SYMOP (left
) ? OP_SYMBOL (left
)->name
: "<no name>");
2472 // there is no need to multiply with 1
2475 size
= operandFromLit (nBytes
);
2476 SPEC_USIGN (getSpec (operandType (size
))) = 1;
2477 indexUnsigned
= IS_UNSIGNED (getSpec (operandType (right
)));
2478 if (!indexUnsigned
&& ptrSize
> INTSIZE
)
2480 SPEC_LONG (getSpec (operandType (size
))) = 1;
2481 SPEC_CVAL (getSpec (operandType (size
))).v_ulong
= nBytes
;
2483 right
= geniCodeMultiply (right
, size
, (ptrSize
>= INTSIZE
) ? RESULT_TYPE_INT
: RESULT_TYPE_CHAR
);
2484 /* Even if right is a 'unsigned char',
2485 the result will be a 'signed int' due to the promotion rules.
2486 It doesn't make sense when accessing arrays, so let's fix it here: */
2488 SPEC_USIGN (getSpec (operandType (right
))) = 1;
2491 if (ptrSize
> getSize (rtype
) && !IS_UNSIGNED (retype
))
2498 type
= newIntLink();
2502 type
= newLongLink();
2507 right
= geniCodeCast (type
, right
, TRUE
);
2510 resType
= copyLinkChain (ltype
);
2513 { // make them the same size
2514 resType
= usualBinaryConversions (&left
, &right
, resultType
, '+');
2517 /* if they are both literals then we know */
2518 if (IS_LITERAL (letype
) && IS_LITERAL (retype
) && left
->isLiteral
&& right
->isLiteral
)
2520 value
*scaledRight
= valFromType (rtype
);
2522 scaledRight
= valMult (scaledRight
, valueFromLit (getSize (ltype
->next
)), true);
2523 return operandFromValue (valPlus (valFromType (ltype
), scaledRight
, true), false);
2526 ic
= newiCode ('+', left
, right
);
2528 IC_RESULT (ic
) = newiTempOperand (resType
, 1);
2529 IC_RESULT (ic
)->isaddr
= (isarray
? 1 : 0);
2531 /* if left or right is a float then support routine */
2532 if (IS_FLOAT (ltype
) || IS_FLOAT (rtype
) || IS_FIXED (ltype
) || IS_FIXED (rtype
))
2537 return IC_RESULT (ic
);
2540 /*-----------------------------------------------------------------*/
2541 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */
2542 /*-----------------------------------------------------------------*/
2544 aggrToPtr (sym_link
* type
, bool force
)
2549 if (IS_PTR (type
) && !force
)
2552 etype
= getSpec (type
);
2553 ptype
= newLink (DECLARATOR
);
2557 /* set the pointer depending on the storage class */
2558 DCL_TYPE (ptype
) = PTR_TYPE (SPEC_OCLS (etype
));
2562 /*------------------------------------------------------------------*/
2563 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2564 /*------------------------------------------------------------------*/
2566 aggrToPtrDclType (sym_link
* type
, bool force
)
2568 if (IS_PTR (type
) && !force
)
2569 return DCL_TYPE (type
);
2571 /* return the pointer depending on the storage class */
2572 return PTR_TYPE (SPEC_OCLS (getSpec (type
)));
2575 /*-----------------------------------------------------------------*/
2576 /* geniCodeArray2Ptr - array to pointer */
2577 /*-----------------------------------------------------------------*/
2579 geniCodeArray2Ptr (operand
* op
)
2581 sym_link
*optype
= operandType (op
);
2582 sym_link
*opetype
= getSpec (optype
);
2584 /* set the pointer depending on the storage class */
2585 DCL_TYPE (optype
) = PTR_TYPE (SPEC_OCLS (opetype
));
2586 /* now remove the storage class from this itemp */
2587 SPEC_SCLS (opetype
) = S_FIXED
;
2588 SPEC_OCLS (opetype
) = NULL
;
2595 /*-----------------------------------------------------------------*/
2596 /* geniCodeArray - array access */
2597 /*-----------------------------------------------------------------*/
2599 geniCodeArray (operand
* left
, operand
* right
, int lvl
, bool noderef
)
2603 sym_link
*ltype
= operandType (left
);
2605 RESULT_TYPE resultType
;
2607 resultType
= (getArraySizePtr (left
) >= INTSIZE
) ? RESULT_TYPE_INT
: RESULT_TYPE_CHAR
;
2608 if (DCL_ELEM (ltype
))
2610 if (DCL_ELEM (ltype
) * getSize (ltype
->next
) <= 255)
2611 resultType
= RESULT_TYPE_CHAR
;
2616 if (IS_PTR (ltype
->next
) && left
->isaddr
)
2618 left
= geniCodeRValue (left
, FALSE
);
2622 return geniCodeAdd (left
, right
, resultType
, lvl
);
2624 return geniCodeDerefPtr (geniCodeAdd (left
, right
, resultType
, lvl
), lvl
);
2626 size
= operandFromLit (getSize (ltype
->next
));
2627 SPEC_USIGN (getSpec (operandType (size
))) = 1;
2628 indexUnsigned
= IS_UNSIGNED (getSpec (operandType (right
)));
2629 right
= geniCodeMultiply (right
, size
, resultType
);
2630 /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2631 It doesn't make sense when accessing arrays, so let's fix it here: */
2633 SPEC_USIGN (getSpec (operandType (right
))) = 1;
2634 /* we can check for limits here */
2635 /* already done in SDCCast.c
2636 if (isOperandLiteral (right) &&
2639 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2641 werror (W_IDX_OUT_OF_BOUNDS,
2642 (int) operandLitValue (right) / getSize (ltype->next),
2647 ic
= newiCode ('+', left
, right
);
2649 IC_RESULT (ic
) = newiTempOperand (((IS_PTR (ltype
) && !IS_AGGREGATE (ltype
->next
) && !IS_PTR (ltype
->next
)) ||
2650 (IS_ARRAY (ltype
) && IS_FUNCPTR (ltype
->next
))) ? ltype
: ltype
->next
, 0);
2652 if (!IS_AGGREGATE (ltype
->next
))
2654 IC_RESULT (ic
)->isaddr
= 1;
2655 IC_RESULT (ic
)->aggr2ptr
= 1;
2659 return IC_RESULT (ic
);
2662 /*-----------------------------------------------------------------*/
2663 /* geniCodeStruct - generates intermediate code for structures */
2664 /*-----------------------------------------------------------------*/
2666 geniCodeStruct (operand
* left
, operand
* right
, bool islval
)
2669 sym_link
*type
= operandType (left
);
2670 sym_link
*etype
= getSpec (type
);
2671 sym_link
*rtype
, *retype
;
2672 symbol
*element
= getStructElement (SPEC_STRUCT (etype
), OP_SYMBOL (right
));
2674 wassert (IS_SYMOP (right
));
2676 wassert (IS_STRUCT (type
) || ((IS_PTR (type
) || IS_ARRAY (type
)) && IS_STRUCT (type
->next
)));
2678 /* add the offset */
2679 ic
= newiCode ('+', left
, operandFromLit (element
->offset
));
2681 IC_RESULT (ic
) = newiTempOperand (element
->type
, 0);
2683 /* preserve the storage & output class of the struct */
2684 /* as well as the volatile attribute */
2685 rtype
= operandType (IC_RESULT (ic
));
2686 retype
= getSpec (rtype
);
2687 SPEC_SCLS (retype
) = SPEC_SCLS (etype
);
2688 SPEC_OCLS (retype
) = SPEC_OCLS (etype
);
2690 if (IS_PTR (element
->type
))
2692 DCL_PTR_CONST (rtype
) |= DCL_PTR_CONST (element
->type
);
2693 DCL_PTR_VOLATILE (rtype
) |= DCL_PTR_VOLATILE (element
->type
);
2694 DCL_PTR_RESTRICT (rtype
) |= DCL_PTR_RESTRICT (element
->type
);
2695 setOperandType (IC_RESULT (ic
), aggrToPtr (operandType (IC_RESULT (ic
)), TRUE
));
2699 SPEC_CONST (retype
) |= SPEC_CONST (etype
);
2700 /*Do not preserve volatile */
2701 SPEC_RESTRICT (retype
) |= SPEC_RESTRICT (etype
);
2704 IC_RESULT (ic
)->isaddr
= (!IS_AGGREGATE (element
->type
));
2707 return (islval
? IC_RESULT (ic
) : geniCodeRValue (IC_RESULT (ic
), TRUE
));
2710 /*-----------------------------------------------------------------*/
2711 /* geniCodePostInc - generate int code for Post increment */
2712 /*-----------------------------------------------------------------*/
2714 geniCodePostInc (operand
* op
)
2718 sym_link
*optype
= operandType (op
);
2720 operand
*rv
= (IS_ITEMP (op
) ? geniCodeRValue (op
, (!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
) : op
);
2721 sym_link
*rvtype
= operandType (rv
);
2723 operand
*srcOp
= rv
;
2725 /* if this is not an address we have trouble */
2728 werror (E_LVALUE_REQUIRED
, "++");
2732 rOp
= newiTempOperand (rvtype
, 0);
2733 OP_SYMBOL (rOp
)->noSpilLoc
= 1;
2736 OP_SYMBOL (rv
)->noSpilLoc
= 1;
2738 geniCodeAssign (rOp
, rv
, 0, 0);
2740 /* If rv is volatile, we can only read it once, and we've just */
2741 /* done that, so use the copy in rOp instead to avoid reading */
2743 if (isOperandVolatile (rv
, FALSE
))
2746 size
= (IS_PTR (rvtype
) ? getSize (rvtype
->next
) : 1);
2748 werror (W_SIZEOF_VOID
);
2749 if (IS_FLOAT (rvtype
))
2750 ic
= newiCode ('+', srcOp
, operandFromValue (constFloatVal ("1.0"), false));
2751 else if (IS_FIXED16X16 (rvtype
))
2752 ic
= newiCode ('+', srcOp
, operandFromValue (constFixed16x16Val ("1.0"), false));
2753 else if (IS_BOOL (rvtype
))
2754 ic
= newiCode ('=', NULL
, operandFromLit (1));
2756 ic
= newiCode ('+', srcOp
, operandFromLit (size
));
2758 IC_RESULT (ic
) = result
= newiTempOperand (rvtype
, 0);
2761 geniCodeAssign (op
, result
, 0, 0);
2767 /*-----------------------------------------------------------------*/
2768 /* geniCodePreInc - generate code for preIncrement */
2769 /*-----------------------------------------------------------------*/
2771 geniCodePreInc (operand
* op
, bool lvalue
)
2774 sym_link
*optype
= operandType (op
);
2775 operand
*rop
= (IS_ITEMP (op
) ? geniCodeRValue (op
, ((!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
)) : op
);
2776 sym_link
*roptype
= operandType (rop
);
2782 werror (E_LVALUE_REQUIRED
, "++");
2786 size
= (IS_PTR (roptype
) ? getSize (roptype
->next
) : 1);
2788 werror (W_SIZEOF_VOID
);
2789 if (IS_FLOAT (roptype
))
2790 ic
= newiCode ('+', rop
, operandFromValue (constFloatVal ("1.0"), false));
2791 else if (IS_FIXED16X16 (roptype
))
2792 ic
= newiCode ('+', rop
, operandFromValue (constFixed16x16Val ("1.0"), false));
2793 else if (IS_BOOL (roptype
))
2794 ic
= newiCode ('=', NULL
, operandFromLit (1));
2796 ic
= newiCode ('+', rop
, operandFromLit (size
));
2797 IC_RESULT (ic
) = result
= newiTempOperand (roptype
, 0);
2800 (void) geniCodeAssign (op
, result
, 0, 0);
2801 if (lvalue
|| (IS_TRUE_SYMOP (op
) && !isOperandVolatile (op
, FALSE
)) || IS_BITVAR (optype
))
2807 /*-----------------------------------------------------------------*/
2808 /* geniCodePostDec - generates code for Post decrement */
2809 /*-----------------------------------------------------------------*/
2811 geniCodePostDec (operand
* op
)
2815 sym_link
*optype
= operandType (op
);
2817 operand
*rv
= (IS_ITEMP (op
) ? geniCodeRValue (op
, ((!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
)) : op
);
2818 sym_link
*rvtype
= operandType (rv
);
2820 operand
*srcOp
= rv
;
2822 /* if this is not an address we have trouble */
2825 werror (E_LVALUE_REQUIRED
, "--");
2829 rOp
= newiTempOperand (rvtype
, 0);
2830 OP_SYMBOL (rOp
)->noSpilLoc
= 1;
2833 OP_SYMBOL (rv
)->noSpilLoc
= 1;
2835 geniCodeAssign (rOp
, rv
, 0, 0);
2837 /* If rv is volatile, we can only read it once, and we've just */
2838 /* done that, so use the copy in rOp instead to avoid reading */
2840 if (isOperandVolatile (rv
, FALSE
))
2843 size
= (IS_PTR (rvtype
) ? getSize (rvtype
->next
) : 1);
2845 werror (W_SIZEOF_VOID
);
2846 if (IS_FLOAT (rvtype
))
2847 ic
= newiCode ('-', srcOp
, operandFromValue (constFloatVal ("1.0"), false));
2848 else if (IS_FIXED16X16 (rvtype
))
2849 ic
= newiCode ('-', srcOp
, operandFromValue (constFixed16x16Val ("1.0"), false));
2850 else if (IS_BOOL (rvtype
))
2851 ic
= newiCode ('!', srcOp
, 0);
2853 ic
= newiCode ('-', srcOp
, operandFromLit (size
));
2855 IC_RESULT (ic
) = result
= newiTempOperand (rvtype
, 0);
2858 geniCodeAssign (op
, result
, 0, 0);
2864 /*-----------------------------------------------------------------*/
2865 /* geniCodePreDec - generate code for pre decrement */
2866 /*-----------------------------------------------------------------*/
2868 geniCodePreDec (operand
* op
, bool lvalue
)
2871 sym_link
*optype
= operandType (op
);
2872 operand
*rop
= (IS_ITEMP (op
) ? geniCodeRValue (op
, ((!op
->aggr2ptr
&& IS_PTR (optype
)) ? TRUE
: FALSE
)) : op
);
2873 sym_link
*roptype
= operandType (rop
);
2879 werror (E_LVALUE_REQUIRED
, "--");
2883 size
= (IS_PTR (roptype
) ? getSize (roptype
->next
) : 1);
2885 werror (W_SIZEOF_VOID
);
2886 if (IS_FLOAT (roptype
))
2887 ic
= newiCode ('-', rop
, operandFromValue (constFloatVal ("1.0"), false));
2888 else if (IS_FIXED16X16 (roptype
))
2889 ic
= newiCode ('-', rop
, operandFromValue (constFixed16x16Val ("1.0"), false));
2890 else if (IS_BOOL (roptype
))
2891 ic
= newiCode ('!', rop
, 0);
2893 ic
= newiCode ('-', rop
, operandFromLit (size
));
2894 IC_RESULT (ic
) = result
= newiTempOperand (roptype
, 0);
2897 (void) geniCodeAssign (op
, result
, 0, 0);
2898 if (lvalue
|| (IS_TRUE_SYMOP (op
) && !isOperandVolatile (op
, FALSE
)) || IS_BITVAR (optype
))
2905 /*-----------------------------------------------------------------*/
2906 /* geniCodeBitwise - gen int code for bitWise operators */
2907 /*-----------------------------------------------------------------*/
2909 geniCodeBitwise (operand
* left
, operand
* right
, int oper
, sym_link
* resType
)
2913 /* Signedness doesn't matter for bit ops, so omit */
2914 /* possible cast if that is the only difference */
2915 if (compareType (resType
, operandType (left
), false) != -2)
2916 left
= geniCodeCast (resType
, left
, TRUE
);
2917 if (compareType (resType
, operandType (right
), false) != -2)
2918 right
= geniCodeCast (resType
, right
, TRUE
);
2920 ic
= newiCode (oper
, left
, right
);
2921 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
2924 return IC_RESULT (ic
);
2927 /*-----------------------------------------------------------------*/
2928 /* geniCodeAddressOf - gens icode for '&' address of operator */
2929 /*-----------------------------------------------------------------*/
2931 geniCodeAddressOf (operand
* op
)
2935 sym_link
*optype
= operandType (op
);
2936 sym_link
*opetype
= getSpec (optype
);
2938 if (IS_ITEMP (op
) && IS_PTR (optype
))
2940 op
= operandFromOperand (op
);
2945 /* lvalue check already done in decorateType */
2946 /* this must be a lvalue */
2947 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2948 /* werror (E_LVALUE_REQUIRED,"&"); */
2952 p
= newLink (DECLARATOR
);
2954 /* set the pointer depending on the storage class */
2955 DCL_TYPE (p
) = PTR_TYPE (SPEC_OCLS (opetype
));
2957 p
->next
= copyLinkChain (optype
);
2959 /* if already a temp */
2962 setOperandType (op
, p
);
2967 /* otherwise make this of the type coming in */
2968 ic
= newiCode (ADDRESS_OF
, op
, operandFromLit (0));
2969 IC_RESULT (ic
) = newiTempOperand (p
, 1);
2970 IC_RESULT (ic
)->isaddr
= 0;
2972 return IC_RESULT (ic
);
2975 /*-----------------------------------------------------------------*/
2976 /* setOClass - sets the output class depending on the pointer type */
2977 /*-----------------------------------------------------------------*/
2979 setOClass (sym_link
* ptr
, sym_link
* spec
)
2981 switch (DCL_TYPE (ptr
))
2984 SPEC_OCLS (spec
) = data
;
2988 SPEC_OCLS (spec
) = generic
;
2992 SPEC_OCLS (spec
) = xdata
;
2996 SPEC_OCLS (spec
) = code
;
3000 SPEC_OCLS (spec
) = idata
;
3004 SPEC_OCLS (spec
) = xstack
;
3008 SPEC_OCLS (spec
) = eeprom
;
3016 /*-----------------------------------------------------------------*/
3017 /* geniCodeDerefPtr - dereference pointer with '*' */
3018 /*-----------------------------------------------------------------*/
3020 geniCodeDerefPtr (operand
*op
, int lvl
)
3022 sym_link
*rtype
, *retype
;
3023 sym_link
*optype
= operandType (op
);
3025 // if this is an array then array access
3026 if (IS_ARRAY (optype
))
3028 // don't worry, this will be optimized out later
3029 return geniCodeArray (op
, operandFromLit (0), lvl
, false);
3032 // just in case someone screws up
3033 wassert (IS_PTR (optype
));
3035 if (IS_TRUE_SYMOP (op
))
3038 op
= geniCodeRValue (op
, TRUE
);
3040 else if (IS_OP_LITERAL (op
))
3042 /* To avoid problems converting a dereferenced literal pointer */
3043 /* back and forth between lvalue and rvalue formats, replace */
3044 /* the literal pointer with an iTemp and assign the literal */
3045 /* value to the iTemp. */
3047 operand
*iop
= newiTempOperand (optype
, 0);
3048 SPEC_SCLS (OP_SYM_ETYPE (iop
)) = S_AUTO
; /* remove S_LITERAL */
3049 iop
->isaddr
= 0; /* assign to the iTemp itself */
3050 ic
= newiCode ('=', NULL
, op
);
3051 IC_RESULT (ic
) = iop
;
3053 op
= operandFromOperand (iop
); /* now use the iTemp as operand */
3054 optype
= operandType (op
);
3057 /* now get rid of the pointer part */
3058 if (isLvaluereq (lvl
) && IS_ITEMP (op
))
3060 retype
= getSpec (rtype
= copyLinkChain (optype
));
3064 retype
= getSpec (rtype
= copyLinkChain (optype
->next
));
3065 /* outputclass needs 2b updated */
3066 setOClass (optype
, retype
);
3069 op
->isGptr
= IS_GENPTR (optype
);
3071 op
->isaddr
= (IS_PTR (rtype
) ||
3072 IS_STRUCT (rtype
) || IS_INT (rtype
) || IS_BITINT (rtype
) || IS_BOOL (rtype
) || IS_CHAR (rtype
) || IS_FLOAT (rtype
) || IS_FIXED (rtype
));
3074 if (!isLvaluereq (lvl
))
3075 op
= geniCodeRValue (op
, TRUE
);
3077 if (IS_DECL (rtype
))
3079 DCL_PTR_ADDRSPACE (rtype
) = 0;
3080 DCL_PTR_VOLATILE (rtype
) = 0;
3084 SPEC_ADDRSPACE (rtype
) = 0;
3085 SPEC_VOLATILE (rtype
) = 0;
3087 setOperandType (op
, rtype
);
3092 /*-----------------------------------------------------------------*/
3093 /* geniCodeUnaryMinus - does a unary minus of the operand */
3094 /*-----------------------------------------------------------------*/
3096 geniCodeUnaryMinus (operand
* op
)
3099 sym_link
*optype
= operandType (op
);
3101 if (IS_LITERAL (optype
))
3102 return operandFromLit (-floatFromVal (OP_VALUE (op
)));
3104 ic
= newiCode (UNARYMINUS
, op
, NULL
);
3105 IC_RESULT (ic
) = newiTempOperand (optype
, 0);
3107 return IC_RESULT (ic
);
3110 /*-----------------------------------------------------------------*/
3111 /* geniCodeLeftShift - gen i code for left shift */
3112 /*-----------------------------------------------------------------*/
3114 geniCodeLeftShift (operand
* left
, operand
* right
, RESULT_TYPE resultType
)
3119 resType
= usualBinaryConversions (&left
, &right
, resultType
, LEFT_OP
);
3120 ic
= newiCode(LEFT_OP
, left
, right
);
3121 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
3123 return IC_RESULT (ic
);
3126 /*-----------------------------------------------------------------*/
3127 /* geniCodeRightShift - gen i code for right shift */
3128 /*-----------------------------------------------------------------*/
3130 geniCodeRightShift (operand
* left
, operand
* right
)
3134 ic
= newiCode (RIGHT_OP
, left
, right
);
3135 IC_RESULT (ic
) = newiTempOperand (operandType (left
), 0);
3137 return IC_RESULT (ic
);
3140 /*-----------------------------------------------------------------*/
3141 /* geniCodeLogic- logic code */
3142 /*-----------------------------------------------------------------*/
3144 geniCodeLogic (operand
* left
, operand
* right
, int op
, ast
* tree
)
3147 sym_link
*ctype
, *ttype
;
3148 sym_link
*rtype
= operandType (right
);
3149 sym_link
*ltype
= operandType (left
);
3151 /* left is integral type and right is literal then
3152 check if the literal value is within bounds */
3153 if (IS_INTEGRAL (ltype
) && IS_VALOP (right
) && IS_LITERAL (rtype
))
3155 CCR_RESULT ccr_result
= checkConstantRange (ltype
, rtype
, op
, FALSE
);
3158 case CCR_ALWAYS_TRUE
:
3159 case CCR_ALWAYS_FALSE
:
3160 werror (W_COMP_RANGE
, "true resp. false");
3161 return operandFromLit (ccr_result
== CCR_ALWAYS_TRUE
? 1 : 0);
3167 /* Avoid expensive comparisons when the type of the constant is bigger than the type of the non-const operand */
3168 if (IS_INTEGRAL (ltype
) && IS_LITERAL (rtype
) && getSize (ltype
) < getSize (rtype
))
3169 right
->svt
.valOperand
= valCastLiteral (ltype
, operandLitValue (right
), operandLitValueUll (right
));
3170 if (IS_INTEGRAL (rtype
) && IS_LITERAL (ltype
) && getSize (rtype
) < getSize (ltype
))
3171 left
->svt
.valOperand
= valCastLiteral (rtype
, operandLitValue (left
), operandLitValueUll (left
));
3173 /* if one operand is a pointer and the other is a literal generic void pointer,
3174 change the type of the literal generic void pointer to match the other pointer */
3175 if (IS_GENPTR (ltype
) && IS_VOID (ltype
->next
) && IS_ITEMP (left
) && IS_PTR (rtype
) && !IS_GENPTR (rtype
))
3177 /* find left's definition */
3181 if (((ic
->op
== CAST
) || (ic
->op
== '=')) && isOperandEqual (left
, IC_RESULT (ic
)))
3186 /* if casting literal to generic pointer, then cast to rtype instead */
3187 if (ic
&& (ic
->op
== CAST
) && isOperandLiteral (IC_RIGHT (ic
)))
3189 left
= operandFromValue (valCastLiteral (rtype
, operandLitValue (IC_RIGHT (ic
)),operandLitValueUll (IC_RIGHT (ic
))), false);
3190 ltype
= operandType (left
);
3193 if (IS_GENPTR (rtype
) && IS_VOID (rtype
->next
) && IS_ITEMP (right
) && IS_PTR (ltype
) && !IS_GENPTR (ltype
))
3195 /* find right's definition */
3199 if (((ic
->op
== CAST
) || (ic
->op
== '=')) && isOperandEqual (right
, IC_RESULT (ic
)))
3204 /* if casting literal to generic pointer, then cast to rtype instead */
3205 if (ic
&& (ic
->op
== CAST
) && isOperandLiteral (IC_RIGHT (ic
)))
3207 right
= operandFromValue (valCastLiteral (ltype
, operandLitValue (IC_RIGHT (ic
)), operandLitValueUll (IC_RIGHT (ic
))), false);
3208 rtype
= operandType (right
);
3212 ctype
= usualBinaryConversions (&left
, &right
, RESULT_TYPE_BOOL
, op
);
3214 ic
= newiCode (op
, left
, right
);
3215 /* store 0 or 1 in result */
3216 ttype
= (tree
&& IS_BOOLEAN (tree
->ftype
)) ? newBoolLink () : newCharLink ();
3217 IC_RESULT (ic
) = newiTempOperand (ttype
, 1);
3219 /* if comparing float
3220 and not a '==' || '!=' || '&&' || '||' (these
3222 if (IS_FLOAT (ctype
) && op
!= EQ_OP
&& op
!= NE_OP
&& op
!= AND_OP
&& op
!= OR_OP
)
3225 /* if comparing a fixed type use support functions */
3226 if (IS_FIXED (ctype
))
3230 return IC_RESULT (ic
);
3233 /*-----------------------------------------------------------------*/
3234 /* geniCodeLogicAndOr - && || operations */
3235 /*-----------------------------------------------------------------*/
3237 geniCodeLogicAndOr (ast
* tree
, int lvl
)
3241 symbol
*falseLabel
= newiTempLabel (NULL
);
3242 symbol
*trueLabel
= newiTempLabel (NULL
);
3243 symbol
*exitLabel
= newiTempLabel (NULL
);
3244 operand
*op
, *result
, *condition
;
3246 /* AND_OP and OR_OP are no longer generated because of bug-905492.
3247 They can be reenabled by executing the following block. If you find
3248 a decent optimization you could start right here:
3253 operand
*leftOp
, *rightOp
;
3255 leftOp
= geniCodeRValue (ast2iCode (tree
->left
, lvl
+ 1), FALSE
);
3256 rightOp
= geniCodeRValue (ast2iCode (tree
->right
, lvl
+ 1), FALSE
);
3258 return geniCodeLogic (leftOp
, rightOp
, tree
->opval
.op
);
3262 /* generate two IFX for the '&&' or '||' op */
3264 /* evaluate left operand */
3265 condition
= ast2iCode (tree
->left
, lvl
+ 1);
3266 op
= geniCodeRValue (condition
, FALSE
);
3268 /* test left operand */
3269 if (tree
->opval
.op
== AND_OP
)
3270 ic
= newiCodeCondition (op
, NULL
, falseLabel
);
3272 ic
= newiCodeCondition (op
, trueLabel
, NULL
);
3275 /* evaluate right operand */
3276 condition
= ast2iCode (tree
->right
, lvl
+ 1);
3277 op
= geniCodeRValue (condition
, FALSE
);
3279 /* test right operand */
3280 ic
= newiCodeCondition (op
, trueLabel
, NULL
);
3283 /* store 0 or 1 in result */
3284 type
= (IS_BOOLEAN (tree
->ftype
)) ? newBoolLink () : newCharLink ();
3285 result
= newiTempOperand (type
, 1);
3287 geniCodeLabel (falseLabel
);
3288 geniCodeAssign (result
, operandFromLit (0), 0, 0);
3289 /* generate an unconditional goto */
3290 geniCodeGoto (exitLabel
);
3292 geniCodeLabel (trueLabel
);
3293 geniCodeAssign (result
, operandFromLit (1), 0, 0);
3295 geniCodeLabel (exitLabel
);
3300 /*-----------------------------------------------------------------*/
3301 /* geniCodeUnary - for a generic unary operation */
3302 /*-----------------------------------------------------------------*/
3304 geniCodeUnary (operand
* op
, int oper
, sym_link
* resType
)
3306 iCode
*ic
= newiCode (oper
, op
, NULL
);
3308 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
3310 return IC_RESULT (ic
);
3313 /*-----------------------------------------------------------------*/
3314 /* geniCodeBinary - for a generic binary operation */
3315 /*-----------------------------------------------------------------*/
3317 geniCodeBinary (operand
* left
, operand
* right
, int oper
, sym_link
* resType
)
3319 iCode
*ic
= newiCode (oper
, left
, right
);
3321 IC_RESULT (ic
) = newiTempOperand (resType
, 0);
3323 return IC_RESULT (ic
);
3326 /*-----------------------------------------------------------------*/
3327 /* geniCodeConditional - geniCode for '?' ':' operation */
3328 /*-----------------------------------------------------------------*/
3330 geniCodeConditional (ast
* tree
, int lvl
)
3333 symbol
*falseLabel
= newiTempLabel (NULL
);
3334 symbol
*exitLabel
= newiTempLabel (NULL
);
3335 ast
*astTrue
= tree
->right
->left
;
3336 ast
*astFalse
= tree
->right
->right
;
3337 operand
*cond
= ast2iCode (tree
->left
, lvl
+ 1);
3338 operand
*result
= newiTempOperand (tree
->ftype
, 0);
3339 operand
*opTrue
, *opFalse
;
3341 ic
= newiCodeCondition (geniCodeRValue (cond
, FALSE
), NULL
, falseLabel
);
3344 opTrue
= ast2iCode (astTrue
, lvl
+ 1);
3346 /* move the value to the new operand */
3347 geniCodeAssign (result
, geniCodeRValue (opTrue
, FALSE
), 0, 0);
3349 /* generate an unconditional goto */
3350 geniCodeGoto (exitLabel
);
3352 /* now for the right side */
3353 geniCodeLabel (falseLabel
);
3355 opFalse
= ast2iCode (astFalse
, lvl
+ 1);
3356 geniCodeAssign (result
, geniCodeRValue (opFalse
, FALSE
), 0, 0);
3358 /* create the exit label */
3359 geniCodeLabel (exitLabel
);
3364 /*-----------------------------------------------------------------*/
3365 /* checkTypes - check types for assignment */
3366 /*-----------------------------------------------------------------*/
3368 checkTypes (operand
* left
, operand
* right
)
3370 sym_link
*ltype
= operandType (left
);
3371 sym_link
*rtype
= operandType (right
);
3372 bool always_cast
= FALSE
;
3374 /* if the left & right type don't exactly match */
3375 /* if pointer set then make sure the check is
3376 done with the type & not the pointer */
3377 /* then cast rights type to left */
3379 /* first check the type for pointer assignment */
3380 if (left
->isaddr
&& IS_PTR (ltype
) && IS_ITEMP (left
) && compareType (ltype
, rtype
, false) <= 0)
3388 ltype
= ltype
->next
;
3392 /* left is integral type and right is literal then
3393 check if the literal value is within bounds */
3394 if (IS_INTEGRAL (ltype
) && right
->type
== VALUE
&& IS_LITERAL (rtype
) &&
3395 checkConstantRange (ltype
, rtype
, '=', FALSE
) == CCR_OVL
)
3397 werror (W_LIT_OVERFLOW
);
3400 if (always_cast
|| compareType (ltype
, rtype
, false) == -1)
3402 if (IS_VOLATILE (ltype
)) // Don't propagate volatile to right side - we don't want volatile iTemps.
3404 ltype
= copyLinkChain (ltype
);
3406 DCL_PTR_VOLATILE (ltype
) = 0;
3408 SPEC_VOLATILE (ltype
) = 0;
3410 right
= geniCodeCast (ltype
, right
, TRUE
);
3412 checkPtrQualifiers (ltype
, rtype
, !right
->isConstElimnated
);
3416 /*-----------------------------------------------------------------*/
3417 /* geniCodeAssign - generate code for assignment */
3418 /*-----------------------------------------------------------------*/
3420 geniCodeAssign (operand
* left
, operand
* right
, int nosupdate
, int strictLval
)
3425 if (!left
->isaddr
&& (!IS_ITEMP (left
) || strictLval
))
3427 werror (E_LVALUE_REQUIRED
, "assignment");
3431 right
= checkTypes (left
, right
);
3433 /* If left is a true symbol & ! volatile
3434 create an assignment to temporary for
3435 the right & then assign this temporary
3436 to the symbol. This is SSA (static single
3437 assignment). Isn't it simple and folks have
3438 published mountains of paper on it */
3439 if (IS_TRUE_SYMOP (left
) && !isOperandVolatile (left
, FALSE
) && isOperandGlobal (left
))
3443 sym_link
*ltype
= operandType (left
);
3445 if (IS_TRUE_SYMOP (right
))
3446 sym
= OP_SYMBOL (right
);
3447 ic
= newiCode ('=', NULL
, right
);
3448 IC_RESULT (ic
) = newRight
= newiTempOperand (ltype
, 0);
3449 /* avoid double fetch from volatile right, see bug 1369874 */
3450 if (!isOperandVolatile (right
, FALSE
))
3451 SPIL_LOC (newRight
) = sym
;
3456 ic
= newiCode ('=', NULL
, right
);
3457 IC_RESULT (ic
) = left
;
3460 /* if left isgptr flag is set then support
3461 routine will be required */
3465 ic
->nosupdate
= nosupdate
;
3466 /* left could be a pointer assignment,
3467 return the properly casted right instead */
3468 ltype
= operandType (left
);
3469 if ((IS_PTR (ltype
) && IS_BITVAR (ltype
->next
)) || IS_BITVAR (ltype
))
3475 /*-----------------------------------------------------------------*/
3476 /* geniCodeDummyRead - generate code for dummy read */
3477 /*-----------------------------------------------------------------*/
3479 geniCodeDummyRead (operand
* op
)
3482 sym_link
*type
= operandType (op
);
3484 if (!IS_VOLATILE (type
))
3487 ic
= newiCode (DUMMY_READ_VOLATILE
, NULL
, op
);
3493 /*-----------------------------------------------------------------*/
3494 /* geniCodeSEParms - generate code for side effecting fcalls */
3495 /*-----------------------------------------------------------------*/
3497 geniCodeSEParms (ast
*parms
, int lvl
)
3502 if (IS_AST_PARAM (parms
))
3504 geniCodeSEParms (parms
->left
, lvl
);
3505 geniCodeSEParms (parms
->right
, lvl
);
3509 /* hack don't like this but too lazy to think of
3511 if (IS_ADDRESS_OF_OP (parms
))
3512 parms
->left
->lvalue
= 1;
3514 if (IS_CAST_OP (parms
) && IS_PTR (parms
->ftype
) && IS_ADDRESS_OF_OP (parms
->right
))
3515 parms
->right
->left
->lvalue
= 1;
3517 if (parms
->type
== EX_OP
&& parms
->opval
.op
== '[' && IS_STRUCT (parms
->ftype
)) // Do not dereference pointer to struct.
3518 parms
->opval
.op
= '+';
3520 parms
->opval
.oprnd
= geniCodeRValue (ast2iCode (parms
, lvl
+ 1), FALSE
);
3521 parms
->type
= EX_OPERAND
;
3522 AST_ARGREG (parms
) = parms
->etype
? SPEC_ARGREG (parms
->etype
) : SPEC_ARGREG (parms
->ftype
);
3525 /*-----------------------------------------------------------------*/
3526 /* geniCodeParms - generates parameters */
3527 /*-----------------------------------------------------------------*/
3529 geniCodeParms (ast
*parms
, value
*argVals
, int *iArg
, int *stack
, sym_link
*ftype
, int lvl
, iCode
*iic_start
)
3538 iic_start
= iCodeChainEnd
;
3540 /* if this is a param node then do the left & right */
3541 if (parms
->type
== EX_OP
&& parms
->opval
.op
== PARAM
)
3543 argVals
= geniCodeParms (parms
->left
, argVals
, iArg
, stack
, ftype
, lvl
, iic_start
);
3544 argVals
= geniCodeParms (parms
->right
, argVals
, iArg
, stack
, ftype
, lvl
, iic_start
);
3548 // Get the parameter value. All the real work for this was done in geniCodeSEParms already.
3549 wassert (parms
->type
== EX_OPERAND
);
3550 pval
= parms
->opval
.oprnd
;
3552 /* if register parm then make it a send */
3553 if ((IS_REGPARM (parms
->etype
) && !IFFUNC_HASVARARGS (ftype
)) || IFFUNC_ISBUILTIN (ftype
))
3555 pval
= checkTypes (operandFromValue (argVals
, true), pval
);
3556 ic
= newiCode (SEND
, pval
, NULL
);
3557 ic
->argreg
= SPEC_ARGREG (parms
->etype
);
3558 ic
->builtinSEND
= FUNC_ISBUILTIN (ftype
);
3563 iCode
*castic_start
= 0;
3564 iCode
*castic_end
= 0;
3565 bool is_structparm
= IS_STRUCT (parms
->ftype
); // struct parameter handling is hackish.
3566 if (iic_start
!= iCodeChainEnd
)
3567 castic_start
= iCodeChainEnd
;
3570 sym_link
*ptr
= newLink (DECLARATOR
);
3571 DCL_TYPE (ptr
) = PTR_TYPE (SPEC_OCLS (getSpec (operandType (pval
))));
3572 ptr
->next
= copyLinkChain (parms
->ftype
);
3573 if (IS_PTR (operandType (pval
)))
3575 pval
= geniCodeCast (ptr
, pval
, true);
3577 setOperandType (pval
, ptr
);
3579 // now decide whether to push or assign
3580 if (!(options
.stackAuto
|| IFFUNC_ISREENT (ftype
)))
3582 if (is_structparm
) // Passing the parameter requires a memcpy.
3584 iCode
*dstic
, *srcic
, *nic
, *callic
, *iic_end
;
3585 // Keep this one in mind in so we can move it later.
3586 operand
*dstop
= geniCodeCast (FUNC_ARGS(builtin_memcpy
->type
)->type
, operandFromValue (argVals
, true), false);
3587 castic_end
= iCodeChainEnd
;
3588 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy
->type
)->etype
))
3590 dstic
= newiCode (SEND
, dstop
, 0);
3591 dstic
->argreg
= SPEC_ARGREG (FUNC_ARGS (builtin_memcpy
->type
)->etype
);
3595 dstic
= newiCode ('=', 0, dstop
);
3596 IC_RESULT (dstic
) = operandFromValue (FUNC_ARGS(builtin_memcpy
->type
), false);
3598 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy
->type
)->next
->etype
))
3600 srcic
= newiCode (SEND
, pval
, 0);
3601 srcic
->argreg
= SPEC_ARGREG (FUNC_ARGS (builtin_memcpy
->type
)->next
->etype
);
3605 srcic
= newiCode ('=', 0, pval
);
3606 IC_RESULT (srcic
) = operandFromValue (FUNC_ARGS(builtin_memcpy
->type
)->next
, false);
3608 if (IS_REGPARM (FUNC_ARGS (builtin_memcpy
->type
)->next
->next
->etype
))
3610 nic
= newiCode (SEND
, operandFromLit (getSize (parms
->ftype
)), 0);
3611 nic
->argreg
= SPEC_ARGREG (FUNC_ARGS (builtin_memcpy
->type
)->next
->next
->etype
);
3615 nic
= newiCode ('=', 0, operandFromLit (getSize (parms
->ftype
)));
3616 IC_RESULT (nic
) = operandFromValue (FUNC_ARGS(builtin_memcpy
->type
)->next
->next
, false);
3618 callic
= newiCode (CALL
, operandFromSymbol (builtin_memcpy
, false), 0);
3619 IC_RESULT (callic
) = newiTempOperand (builtin_memcpy
->type
->next
, 0);
3620 // Insert before passing any other parameters - otherwise register parameters to the function will instead end up as parameters to the memcpy call.
3623 iCode
*castic
= castic_start
->next
;
3624 // Cut out cast from where it is.
3625 castic_start
->next
= castic_end
->next
;
3626 if (castic_end
->next
)
3627 castic_end
->next
->prev
= castic_start
;
3628 if (castic_end
== iCodeChainEnd
)
3629 iCodeChainEnd
= castic_start
;
3630 // Insert it earlier.
3631 iic_end
= iic_start
->next
;
3632 iic_start
->next
= castic
;
3633 castic
->prev
= iic_start
;
3634 castic_end
->next
= iic_end
;
3636 iic_end
->prev
= castic_end
;
3638 iic_start
= castic_end
;
3639 iic_end
= iic_start
->next
;
3640 iic_start
->next
= dstic
;
3641 dstic
->prev
= iic_start
;
3642 dstic
->next
= srcic
;
3643 srcic
->prev
= dstic
;
3648 callic
->next
= iic_end
;
3650 iic_end
->prev
= callic
;
3651 else if (iic_start
== iCodeChainEnd
)
3652 iCodeChainEnd
= callic
;
3657 operand
*top
= operandFromValue (argVals
, true);
3658 // clear useDef and other bitVectors
3659 OP_USES (top
) = OP_DEFS (top
) = OP_SYMBOL (top
)->clashes
= 0;
3660 geniCodeAssign (top
, pval
, 1, 0);
3665 if (argVals
&& (*iArg
>= 0))
3666 pval
= checkTypes (operandFromValue (argVals
, false), pval
);
3669 ic
= newiCode (IPUSH_VALUE_AT_ADDRESS
, pval
, operandFromLit (0));
3671 ic
= newiCode (IPUSH
, pval
, NULL
);
3673 // update the stack adjustment
3674 sym_link
*parmtype
= IS_ARRAY (parms
->ftype
) ? aggrToPtr (parms
->ftype
, false) : parms
->ftype
;
3675 *stack
+= getSize (parmtype
);
3676 if (IFFUNC_ISSMALLC (ftype
) && getSize (parmtype
) == 1) // SmallC calling convention passes 8-bit parameters as 16-bit values.
3678 if (TARGET_PDK_LIKE
&& getSize (parmtype
) % 2) // So does pdk due to stack alignment requirements.
3686 assert (argVals
!= NULL
);
3687 argVals
= argVals
->next
;
3693 /*-----------------------------------------------------------------*/
3694 /* geniCodeCall - generates temp code for calling */
3695 /*-----------------------------------------------------------------*/
3697 geniCodeCall (operand
* left
, ast
* parms
, int lvl
)
3700 sym_link
*type
, *etype
;
3705 if (IS_ARRAY (operandType (left
)))
3710 tic
= newiCode (GET_VALUE_AT_ADDRESS
, left
, operandFromLit (0));
3711 ttype
= copyLinkChain (operandType (left
)->next
);
3712 IC_RESULT (tic
) = newiTempOperand (ttype
, 1);
3713 IC_RESULT (tic
)->isaddr
= IS_FUNCPTR (ttype
) ? 1 : 0;
3715 left
= IC_RESULT (tic
);
3718 ftype
= operandType (left
);
3719 if (!IS_FUNC (ftype
) && !IS_FUNCPTR (ftype
))
3721 werror (E_FUNCTION_EXPECTED
);
3722 return operandFromValue (valueFromLit (0), false);
3725 // C2X unreachable. Just omit the call for now. TODO: Optimize based on this (remove preceding and subsequent icodes, up to whole basic block when no side effects)
3726 if (!IS_FUNCPTR (ftype
) && !strcmp(OP_SYMBOL (left
)->name
, "__builtin_unreachable"))
3729 // not allow call a critical function
3730 if (inCriticalPair
&& FUNC_ISCRITICAL (ftype
))
3731 werror (E_INVALID_CRITICAL
);
3733 /* take care of parameters with side-effecting
3734 function calls in them, this is required to take care
3735 of overlaying function parameters */
3736 geniCodeSEParms (parms
, lvl
);
3738 if (IS_FUNCPTR (ftype
))
3739 ftype
= ftype
->next
;
3741 /* first the parameters */
3742 if ((options
.stackAuto
|| IFFUNC_ISREENT (ftype
)) && !IFFUNC_ISBUILTIN (ftype
))
3749 //count expected arguments except varargs
3750 for (argVals
= FUNC_ARGS (ftype
); argVals
; argVals
= argVals
->next
)
3752 //count actual parameters including varargs
3753 for (parm
= parms
; parm
&& parm
->type
== EX_OP
&& parm
->opval
.op
== PARAM
; parm
= parm
->right
)
3760 argVals
= FUNC_ARGS (ftype
);
3761 iArg
= nArgs
- nParms
;
3763 // reverse the argVals to match the parms
3764 argVals
= reverseVal (argVals
);
3765 geniCodeParms (parms
, argVals
, &iArg
, &stack
, ftype
, lvl
, 0);
3766 argVals
= reverseVal (argVals
);
3770 geniCodeParms (parms
, FUNC_ARGS (ftype
), &iArg
, &stack
, ftype
, lvl
, 0);
3773 /* now call : if symbol then pcall */
3774 if (IS_OP_POINTER (left
) || IS_ITEMP (left
))
3776 ic
= newiCode (PCALL
, left
, NULL
);
3780 ic
= newiCode (CALL
, left
, NULL
);
3783 type
= copyLinkChain (ftype
->next
);
3784 etype
= getSpec (type
);
3785 SPEC_EXTR (etype
) = 0;
3789 /* stack adjustment after call */
3790 ic
->parmBytes
= stack
;
3792 if (!IS_STRUCT (type
))
3794 IC_RESULT (ic
) = newiTempOperand (type
, 1);
3795 return IC_RESULT (ic
);
3799 symbol
*sym
= newSymbol (genSymName (ic
->level
), 1);
3800 sym
->type
= copyLinkChain (type
);
3801 sym
->etype
= getSpec (sym
->type
);
3802 SPEC_SCLS (sym
->etype
) = S_AUTO
;
3803 SPEC_OCLS (sym
->etype
) = NULL
;
3804 SPEC_EXTR (sym
->etype
) = 0;
3805 SPEC_STAT (sym
->etype
) = 0;
3806 stack
= allocVariables (sym
);
3807 currFunc
->stack
+= options
.useXstack
? 0 : stack
;
3808 currFunc
->xstack
+= options
.useXstack
? stack
: 0;
3809 IC_RESULT (ic
) = operandFromSymbol (sym
, false);
3810 return (operandFromSymbol (sym
, true));
3814 /*-----------------------------------------------------------------*/
3815 /* geniCodeReceive - generate intermediate code for "receive" */
3816 /*-----------------------------------------------------------------*/
3818 geniCodeReceive (value
* args
, operand
* func
)
3820 unsigned char paramByteCounter
= 0;
3822 /* for all arguments that are passed in registers */
3825 if (IS_REGPARM (args
->etype
))
3827 operand
*opr
= operandFromValue (args
, true);
3829 symbol
*sym
= OP_SYMBOL (opr
);
3832 /* we will use it after all optimizations
3833 and before liveRange calculation */
3834 if (!sym
->addrtaken
&& !IS_VOLATILE (sym
->etype
))
3837 if ((IN_FARSPACE (SPEC_OCLS (sym
->etype
)) && !TARGET_HC08_LIKE
&& !TARGET_MOS6502_LIKE
) &&
3838 options
.stackAuto
== 0 && (!(options
.model
== MODEL_FLAT24
)))
3843 opl
= newiTempOperand (args
->type
, 0);
3845 sym
->reqv
->key
= sym
->key
;
3846 OP_SYMBOL (sym
->reqv
)->key
= sym
->key
;
3847 OP_SYMBOL (sym
->reqv
)->isreqv
= 1;
3848 OP_SYMBOL (sym
->reqv
)->islocal
= 0;
3849 SPIL_LOC (sym
->reqv
) = sym
;
3853 ic
= newiCode (RECEIVE
, func
, NULL
);
3854 ic
->argreg
= SPEC_ARGREG (args
->etype
);
3855 if (ic
->argreg
== 1)
3857 currFunc
->recvSize
= getSize (sym
->type
);
3859 IC_RESULT (ic
) = opr
;
3861 /* misuse of parmBytes (normally used for functions)
3862 * to save estimated stack position of this argument.
3863 * Normally this should be zero for RECEIVE iCodes.
3864 * No idea if this causes side effects on other ports. - dw
3866 ic
->parmBytes
= paramByteCounter
;
3868 /* what stack position do we have? */
3869 paramByteCounter
+= getSize (sym
->type
);
3878 /*-----------------------------------------------------------------*/
3879 /* geniCodeFunctionBody - create the function body */
3880 /*-----------------------------------------------------------------*/
3882 geniCodeFunctionBody (ast
* tree
, int lvl
)
3888 short functionBlock
;
3890 /* reset the auto generation */
3896 func
= ast2iCode (tree
->left
, lvl
+ 1);
3898 savefilename
= filename
;
3899 savelineno
= lineno
;
3900 filename
= OP_SYMBOL (func
)->fileDef
;
3901 lineno
= OP_SYMBOL (func
)->lineDef
;
3902 /* create an entry label */
3903 geniCodeLabel (entryLabel
);
3904 filename
= savefilename
;
3905 lineno
= savelineno
;
3907 /* create a proc icode */
3908 functionBlock
= block
;
3909 ic
= newiCode (FUNCTION
, func
, NULL
);
3910 filename
= ic
->filename
= OP_SYMBOL (func
)->fileDef
;
3911 lineno
= ic
->lineno
= OP_SYMBOL (func
)->lineDef
;
3916 /* for all parameters that are passed
3917 on registers add a "receive" */
3918 geniCodeReceive (tree
->values
.args
, func
);
3920 /* generate code for the body */
3921 ast2iCode (tree
->right
, lvl
+ 1);
3923 /* create a label for return */
3924 block
= functionBlock
;
3925 geniCodeLabel (returnLabel
);
3927 /* now generate the end proc */
3928 ic
= newiCode (ENDFUNCTION
, func
, NULL
);
3929 ic
->filename
= OP_SYMBOL (func
)->fileDef
;
3930 ic
->lineno
= OP_SYMBOL (func
)->lastLine
;
3936 /*-----------------------------------------------------------------*/
3937 /* geniCodeReturn - gen icode for 'return' statement */
3938 /*-----------------------------------------------------------------*/
3940 geniCodeReturn (operand
* op
)
3944 /* return in _Noreturn function */
3945 if (currFunc
&& IFFUNC_ISNORETURN (currFunc
->type
))
3946 werror (W_NORETURNRETURN
);
3948 /* check if a cast is needed */
3949 if (op
&& currFunc
&& currFunc
->type
&& currFunc
->type
->next
)
3950 checkPtrQualifiers (currFunc
->type
->next
, operandType (op
), !op
->isConstElimnated
);
3952 /* if the operand is present force an rvalue */
3954 op
= geniCodeRValue (op
, FALSE
);
3956 ic
= newiCode (RETURN
, op
, NULL
);
3960 /*-----------------------------------------------------------------*/
3961 /* geniCodeIfx - generates code for extended if statement */
3962 /*-----------------------------------------------------------------*/
3964 geniCodeIfx (ast
* tree
, int lvl
)
3967 operand
*condition
= ast2iCode (tree
->left
, lvl
+ 1);
3970 /* if condition is null then exit */
3974 condition
= geniCodeRValue (condition
, FALSE
);
3976 cetype
= getSpec (operandType (condition
));
3977 /* if the condition is a literal */
3978 if (IS_LITERAL (cetype
))
3980 if (floatFromVal (OP_VALUE (condition
)))
3982 if (tree
->trueLabel
)
3983 geniCodeGoto (tree
->trueLabel
);
3989 if (tree
->falseLabel
)
3990 geniCodeGoto (tree
->falseLabel
);
3995 if (tree
->trueLabel
)
3997 ic
= newiCodeCondition (condition
, tree
->trueLabel
, NULL
);
4000 if (tree
->falseLabel
)
4001 geniCodeGoto (tree
->falseLabel
);
4005 ic
= newiCodeCondition (condition
, NULL
, tree
->falseLabel
);
4010 if (tree
->right
&& tree
->right
->type
== EX_VALUE
)
4011 geniCodeDummyRead (ast2iCode (tree
->right
, lvl
+ 1));
4013 ast2iCode (tree
->right
, lvl
+ 1);
4016 /*-----------------------------------------------------------------*/
4017 /* geniCodeJumpTable - tries to create a jump table for switch */
4018 /*-----------------------------------------------------------------*/
4020 geniCodeJumpTable (operand
* cond
, value
* caseVals
, ast
* tree
)
4022 int min
, max
, cnt
= 1;
4024 value
*vch
, *maxVal
;
4028 sym_link
*cetype
= getSpec (operandType (cond
));
4029 int sizeofMinCost
, sizeofZeroMinCost
, sizeofMaxCost
;
4030 int sizeofMatchJump
, sizeofJumpTable
;
4034 if (!tree
|| !caseVals
)
4037 /* the criteria for creating a jump table is */
4038 /* all integer numbers between the maximum & minimum must */
4039 /* be present, the maximum value should not exceed 255 */
4040 /* If not all integer numbers are present the algorithm */
4041 /* inserts jumps to the default label for the missing numbers */
4042 /* and decides later whether it is worth it */
4043 min
= (int) ulFromVal (vch
= caseVals
);
4050 max
= (int) ulFromVal (vch
);
4055 /* Exit if the range is too large to handle with a jump table. */
4056 if (1 + max
- min
> port
->jumptableCost
.maxCount
)
4059 switch (getSize (operandType (cond
)))
4074 /* Compute the size cost of the range check and subtraction. */
4076 sizeofZeroMinCost
= 0;
4079 if (!(min
== 0 && IS_UNSIGNED (cetype
)))
4080 sizeofMinCost
= port
->jumptableCost
.sizeofRangeCompare
[sizeIndex
];
4081 if (!IS_UNSIGNED (cetype
))
4082 sizeofZeroMinCost
= port
->jumptableCost
.sizeofRangeCompare
[sizeIndex
];
4083 sizeofMaxCost
= port
->jumptableCost
.sizeofRangeCompare
[sizeIndex
];
4086 sizeofMinCost
+= port
->jumptableCost
.sizeofSubtract
;
4088 /* If the size cost of handling a non-zero minimum exceeds the */
4089 /* cost of extending the range down to zero, then it might be */
4090 /* better to extend the range to zero. */
4091 if (min
> 0 && (sizeofMinCost
- sizeofZeroMinCost
) >= (min
* port
->jumptableCost
.sizeofElement
))
4093 /* Only extend the jump table if it would still be manageable. */
4094 if (1 + max
<= port
->jumptableCost
.maxCount
)
4097 if (IS_UNSIGNED (cetype
))
4100 sizeofMinCost
= port
->jumptableCost
.sizeofRangeCompare
[sizeIndex
];
4104 /* Compute the total size cost of a jump table. */
4105 sizeofJumpTable
= (1 + max
- min
) * port
->jumptableCost
.sizeofElement
4106 + port
->jumptableCost
.sizeofDispatch
+ sizeofMinCost
+ sizeofMaxCost
;
4108 /* Compute the total size cost of a match & jump sequence */
4109 sizeofMatchJump
= cnt
* port
->jumptableCost
.sizeofMatchJump
[sizeIndex
];
4111 /* If the size cost of the jump table is uneconomical then exit */
4112 if (sizeofMatchJump
< sizeofJumpTable
)
4115 /* The jump table is preferable. */
4117 /* First, a label for the default or missing cases. */
4118 dbuf_init (&dbuf
, 128);
4119 if (tree
->values
.switchVals
.swDefault
)
4121 dbuf_printf (&dbuf
, "_default_%d%s", tree
->values
.switchVals
.swNum
,
4122 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4126 dbuf_printf (&dbuf
, "_swBrk_%d%s", tree
->values
.switchVals
.swNum
,
4127 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4129 falseLabel
= newiTempLabel (dbuf_c_str (&dbuf
));
4130 dbuf_destroy (&dbuf
);
4132 /* Build the list of labels for the jump table. */
4134 t
= (int) ulFromVal (vch
);
4135 for (i
= min
; i
<= max
; i
++)
4139 dbuf_init (&dbuf
, 128);
4140 /* Explicit case: make a new label for it. */
4141 dbuf_printf (&dbuf
, "_case_%d_%d%s", tree
->values
.switchVals
.swNum
, i
,
4142 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4143 addSet (&labels
, newiTempLabel (dbuf_c_str (&dbuf
)));
4144 dbuf_destroy (&dbuf
);
4147 t
= (int) ulFromVal (vch
);
4151 /* Implicit case: use the default label. */
4152 addSet (&labels
, falseLabel
);
4156 /* first we rule out the boundary conditions */
4160 sym_link
*cetype
= getSpec (operandType (cond
));
4161 /* no need to check the lower bound if
4162 the condition is always >= min or
4163 the condition is unsigned & minimum value is zero */
4164 if ((checkConstantRange (cetype
, caseVals
->etype
, '<', FALSE
) != CCR_ALWAYS_FALSE
) &&
4165 (!(min
== 0 && IS_UNSIGNED (cetype
))))
4167 lit
= operandFromValue (valCastLiteral (cetype
, min
, min
), false);
4168 boundary
= geniCodeLogic (cond
, lit
, '<', NULL
);
4169 ic
= newiCodeCondition (boundary
, falseLabel
, NULL
);
4173 /* now for upper bounds */
4174 if (checkConstantRange (cetype
, maxVal
->etype
, '>', FALSE
) != CCR_ALWAYS_FALSE
)
4176 lit
= operandFromValue (valCastLiteral (cetype
, max
, max
), false);
4177 boundary
= geniCodeLogic (cond
, lit
, '>', NULL
);
4178 ic
= newiCodeCondition (boundary
, falseLabel
, NULL
);
4183 /* if the min is not zero then we now make it zero */
4186 cond
= geniCodeSubtract (cond
, operandFromLit (min
), RESULT_TYPE_CHAR
);
4187 if (!IS_LITERAL (getSpec (operandType (cond
))))
4188 setOperandType (cond
, UCHARTYPE
);
4191 /* now create the jumptable */
4192 ic
= newiCode (JUMPTABLE
, NULL
, NULL
);
4193 IC_JTCOND (ic
) = cond
;
4194 IC_JTLABELS (ic
) = labels
;
4199 /*-----------------------------------------------------------------*/
4200 /* geniCodeSwitch - changes a switch to a if statement */
4201 /*-----------------------------------------------------------------*/
4203 geniCodeSwitch (ast
* tree
, int lvl
)
4206 operand
*cond
= geniCodeRValue (ast2iCode (tree
->left
, lvl
+ 1), FALSE
);
4207 value
*caseVals
= tree
->values
.switchVals
.swVals
;
4208 symbol
*trueLabel
, *falseLabel
;
4211 /* If the condition is a literal, then just jump to the */
4212 /* appropriate case label. */
4213 if (IS_LITERAL (getSpec (operandType (cond
))))
4215 int switchVal
, caseVal
;
4217 switchVal
= (int) ulFromVal (OP_VALUE (cond
));
4220 caseVal
= (int) ulFromVal (caseVals
);
4221 if (caseVal
== switchVal
)
4225 dbuf_init (&dbuf
, 128);
4226 dbuf_printf (&dbuf
, "_case_%d_%d%s", tree
->values
.switchVals
.swNum
, caseVal
,
4227 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4228 trueLabel
= newiTempLabel (dbuf_c_str (&dbuf
));
4229 dbuf_destroy (&dbuf
);
4230 geniCodeGoto (trueLabel
);
4233 caseVals
= caseVals
->next
;
4235 goto defaultOrBreak
;
4238 /* If cond is volatile, it might change while we are trying to */
4239 /* find the matching case. To avoid this possibility, make a */
4240 /* non-volatile copy to use instead. */
4241 if (IS_OP_VOLATILE (cond
))
4246 newcond
= newiTempOperand (operandType (cond
), TRUE
);
4247 newcond
->isvolatile
= 0;
4248 ic
= newiCode ('=', NULL
, cond
);
4249 IC_RESULT (ic
) = newcond
;
4254 /* if we can make this a jump table */
4255 if (geniCodeJumpTable (cond
, caseVals
, tree
))
4256 goto jumpTable
; /* no need for the comparison */
4258 /* for the cases defined do */
4261 operand
*compare
= geniCodeLogic (cond
, operandFromValue (caseVals
, true), EQ_OP
, NULL
);
4263 dbuf_init (&dbuf
, 128);
4264 dbuf_printf (&dbuf
, "_case_%d_%d%s", tree
->values
.switchVals
.swNum
, (int) ulFromVal (caseVals
),
4265 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4266 trueLabel
= newiTempLabel (dbuf_c_str (&dbuf
));
4267 dbuf_destroy (&dbuf
);
4269 ic
= newiCodeCondition (compare
, trueLabel
, NULL
);
4271 caseVals
= caseVals
->next
;
4275 /* if default is present then goto break else break */
4276 dbuf_init (&dbuf
, 128);
4277 if (tree
->values
.switchVals
.swDefault
)
4279 dbuf_printf (&dbuf
, "_default_%d%s", tree
->values
.switchVals
.swNum
,
4280 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4284 dbuf_printf (&dbuf
, "_swBrk_%d%s", tree
->values
.switchVals
.swNum
,
4285 tree
->values
.switchVals
.swSuffix
? tree
->values
.switchVals
.swSuffix
: "");
4288 falseLabel
= newiTempLabel (dbuf_c_str (&dbuf
));
4289 dbuf_destroy (&dbuf
);
4290 geniCodeGoto (falseLabel
);
4293 ast2iCode (tree
->right
, lvl
+ 1);
4296 /*-----------------------------------------------------------------*/
4297 /* geniCodeInline - intermediate code for inline assembler */
4298 /*-----------------------------------------------------------------*/
4300 geniCodeInline (ast
* tree
)
4304 ic
= newiCode (INLINEASM
, NULL
, NULL
);
4305 IC_INLINE (ic
) = tree
->values
.inlineasm
;
4309 /*-----------------------------------------------------------------*/
4310 /* geniCodeArrayInit - intermediate code for array initializer */
4311 /*-----------------------------------------------------------------*/
4313 geniCodeArrayInit (ast
* tree
, operand
* array
)
4317 if (!getenv ("TRY_THE_NEW_INITIALIZER"))
4319 ic
= newiCode (ARRAYINIT
, array
, NULL
);
4320 IC_ARRAYILIST (ic
) = tree
->values
.constlist
;
4324 operand
*left
= newOperand (), *right
= newOperand ();
4325 left
->type
= right
->type
= SYMBOL
;
4326 OP_SYMBOL (left
) = AST_SYMBOL (tree
->left
);
4327 OP_SYMBOL (right
) = AST_SYMBOL (tree
->right
);
4328 ic
= newiCode (ARRAYINIT
, left
, right
);
4333 /*-----------------------------------------------------------------*/
4334 /* geniCodeCritical - intermediate code for a critical statement */
4335 /*-----------------------------------------------------------------*/
4337 geniCodeCritical (ast
* tree
, int lvl
)
4343 if (!options
.stackAuto
&& !TARGET_HC08_LIKE
&& !TARGET_MOS6502_LIKE
)
4345 type
= newLink (SPECIFIER
);
4346 SPEC_VOLATILE (type
) = 1;
4347 SPEC_NOUN (type
) = V_BIT
;
4348 SPEC_SCLS (type
) = S_BIT
;
4349 SPEC_BLEN (type
) = 1;
4350 SPEC_BSTR (type
) = 0;
4351 op
= newiTempOperand (type
, 1);
4354 /* If op is NULL, the original interrupt state will saved on */
4355 /* the stack. Otherwise, it will be saved in op. */
4357 /* Generate a save of the current interrupt state & disable */
4359 ic
= newiCode (CRITICAL
, NULL
, NULL
);
4360 IC_RESULT (ic
) = op
;
4363 /* Generate the critical code sequence */
4364 if (tree
->left
&& tree
->left
->type
== EX_VALUE
)
4365 geniCodeDummyRead (ast2iCode (tree
->left
, lvl
+ 1));
4367 ast2iCode (tree
->left
, lvl
+ 1);
4369 /* Generate a restore of the original interrupt state */
4370 ic
= newiCode (ENDCRITICAL
, NULL
, op
);
4375 /*-----------------------------------------------------------------*/
4376 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
4377 /* particular case. Ie : assigning or dereferencing array or ptr */
4378 /*-----------------------------------------------------------------*/
4379 set
*lvaluereqSet
= NULL
;
4380 typedef struct lvalItem
4387 /*-----------------------------------------------------------------*/
4388 /* addLvaluereq - add a flag for lvalreq for current ast level */
4389 /*-----------------------------------------------------------------*/
4391 addLvaluereq (int lvl
)
4393 lvalItem
*lpItem
= (lvalItem
*) Safe_alloc (sizeof (lvalItem
));
4396 addSetHead (&lvaluereqSet
, lpItem
);
4399 /*-----------------------------------------------------------------*/
4400 /* delLvaluereq - del a flag for lvalreq for current ast level */
4401 /*-----------------------------------------------------------------*/
4405 lvalItem
*lpItem
= getSet (&lvaluereqSet
);
4410 /*-----------------------------------------------------------------*/
4411 /* clearLvaluereq - clear lvalreq flag */
4412 /*-----------------------------------------------------------------*/
4416 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4421 /*-----------------------------------------------------------------*/
4422 /* getLvaluereq - get the last lvalreq level */
4423 /*-----------------------------------------------------------------*/
4428 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4434 /*-----------------------------------------------------------------*/
4435 /* isLvaluereq - is lvalreq valid for this level ? */
4436 /*-----------------------------------------------------------------*/
4438 isLvaluereq (int lvl
)
4440 lvalItem
*lpItem
= peekSet (lvaluereqSet
);
4442 return ((lpItem
->req
) && (lvl
<= (lpItem
->lvl
+ 1)));
4446 /*-----------------------------------------------------------------*/
4447 /* ast2iCode - creates an icodeList from an ast */
4448 /*-----------------------------------------------------------------*/
4450 ast2iCode (ast
* tree
, int lvl
)
4452 operand
*left
= NULL
;
4453 operand
*right
= NULL
;
4457 /* set the global variables for filename & line number */
4459 filename
= tree
->filename
;
4461 lineno
= tree
->lineno
;
4463 block
= tree
->block
;
4465 scopeLevel
= tree
->level
;
4467 seqPoint
= tree
->seqPoint
;
4469 if (tree
->type
== EX_VALUE
)
4470 return operandFromValue (tree
->opval
.val
, true);
4472 if (tree
->type
== EX_LINK
)
4473 return operandFromLink (tree
->opval
.lnk
);
4475 /* if we find a nullop */
4476 if (tree
->type
== EX_OP
&& (tree
->opval
.op
== NULLOP
|| tree
->opval
.op
== BLOCK
))
4478 int oldInlinedActive
= inlinedActive
;
4481 if (tree
->left
&& tree
->left
->type
== EX_VALUE
)
4482 geniCodeDummyRead (ast2iCode (tree
->left
, lvl
+ 1));
4484 ast2iCode (tree
->left
, lvl
+ 1);
4485 if (tree
->right
&& tree
->right
->type
== EX_VALUE
)
4486 geniCodeDummyRead (ast2iCode (tree
->right
, lvl
+ 1));
4488 ast2iCode (tree
->right
, lvl
+ 1);
4489 inlinedActive
= oldInlinedActive
;
4493 /* special cases for not evaluating */
4494 if (tree
->opval
.op
!= ':' &&
4495 tree
->opval
.op
!= '?' &&
4496 tree
->opval
.op
!= CALL
&&
4497 tree
->opval
.op
!= IFX
&&
4498 tree
->opval
.op
!= AND_OP
&&
4499 tree
->opval
.op
!= OR_OP
&&
4500 tree
->opval
.op
!= LABEL
&&
4501 tree
->opval
.op
!= GOTO
&&
4502 tree
->opval
.op
!= SWITCH
&& tree
->opval
.op
!= FUNCTION
&& tree
->opval
.op
!= INLINEASM
&& tree
->opval
.op
!= CRITICAL
)
4504 if (IS_ASSIGN_OP (tree
->opval
.op
) || IS_DEREF_OP (tree
) || IS_ADDRESS_OF_OP (tree
))
4507 if ((!IS_ADDRESS_OF_OP (tree
) && IS_ARRAY_OP (tree
->left
) && IS_ARRAY_OP (tree
->left
->left
) &&
4508 tree
->left
->left
->ftype
&& IS_ARRAY (tree
->left
->left
->ftype
) &&
4509 tree
->left
->left
->ftype
->next
&& IS_ARRAY (tree
->left
->left
->ftype
->next
)) ||
4510 (IS_DEREF_OP (tree
) && IS_ARRAY_OP (tree
->left
)))
4513 left
= operandFromAst (tree
->left
, lvl
, true);
4515 if (IS_DEREF_OP (tree
) && IS_DEREF_OP (tree
->left
))
4516 left
= geniCodeRValue (left
, TRUE
);
4520 left
= operandFromAst (tree
->left
, lvl
, true);
4522 if (tree
->opval
.op
== INC_OP
|| tree
->opval
.op
== DEC_OP
)
4525 right
= operandFromAst (tree
->right
, lvl
, true);
4530 right
= operandFromAst (tree
->right
, lvl
, tree
->opval
.op
!= RETURN
);
4534 /* now depending on the type of operand */
4535 /* this will be a biggy */
4536 switch (tree
->opval
.op
)
4538 case '[': /* array operation */
4540 //sym_link *ltype = operandType (left);
4541 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4542 left
= geniCodeRValue (left
, FALSE
);
4543 right
= geniCodeRValue (right
, TRUE
);
4546 return geniCodeArray (left
, right
, lvl
, false);
4548 case '.': /* structure dereference */
4549 if (IS_PTR (operandType (left
)))
4550 left
= geniCodeRValue (left
, TRUE
);
4552 left
= geniCodeRValue (left
, FALSE
);
4554 return geniCodeStruct (left
, right
, tree
->lvalue
);
4556 case PTR_OP
: /* structure pointer dereference */
4559 pType
= operandType (left
);
4560 left
= geniCodeRValue (left
, TRUE
);
4562 setOClass (pType
, getSpec (operandType (left
)));
4565 return geniCodeStruct (left
, right
, tree
->lvalue
);
4567 case INC_OP
: /* increment operator */
4569 return geniCodePostInc (left
);
4571 return geniCodePreInc (right
, tree
->lvalue
);
4573 case DEC_OP
: /* decrement operator */
4575 return geniCodePostDec (left
);
4577 return geniCodePreDec (right
, tree
->lvalue
);
4579 case '&': /* bitwise and or address of operator */
4581 { /* this is a bitwise operator */
4582 left
= geniCodeRValue (left
, FALSE
);
4583 right
= geniCodeRValue (right
, FALSE
);
4584 return geniCodeBitwise (left
, right
, BITWISEAND
, tree
->ftype
);
4587 return geniCodeAddressOf (left
);
4589 case '|': /* bitwise or & xor */
4591 return geniCodeBitwise (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4594 return geniCodeDivision (geniCodeRValue (left
, FALSE
),
4595 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), false);
4598 return geniCodeModulus (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4601 return geniCodeMultiply (geniCodeRValue (left
, FALSE
),
4602 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4604 return geniCodeDerefPtr (geniCodeRValue (left
, FALSE
), lvl
);
4608 return geniCodeSubtract (geniCodeRValue (left
, FALSE
),
4609 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4611 return geniCodeUnaryMinus (geniCodeRValue (left
, FALSE
));
4615 return geniCodeAdd (geniCodeRValue (left
, FALSE
),
4616 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), lvl
);
4618 return geniCodeRValue (left
, FALSE
); /* unary '+' has no meaning */
4621 return geniCodeLeftShift (geniCodeRValue (left
, FALSE
),
4622 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
));
4625 return geniCodeRightShift (geniCodeRValue (left
, FALSE
), geniCodeRValue (right
, FALSE
));
4627 #if 0 // this indeed needs a second thought
4631 // let's keep this simple: get the rvalue we need
4632 op
= geniCodeRValue (right
, FALSE
);
4633 // now cast it to whatever we want
4634 op
= geniCodeCast (operandType (left
), op
, FALSE
);
4635 // if this is going to be used as an lvalue, make it so
4642 #else // bug #604575, is it a bug ????
4643 return geniCodeCast (operandType (left
), geniCodeRValue (right
, FALSE
), FALSE
);
4647 return geniCodeUnary (geniCodeRValue (left
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4651 operand
*op
= geniCodeUnary (geniCodeRValue (left
, FALSE
), tree
->opval
.op
, tree
->ftype
);
4656 operand
*op
= geniCodeBinary (geniCodeRValue (left
, false),
4657 geniCodeRValue (right
, false),
4658 tree
->opval
.op
, tree
->ftype
);
4663 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4664 geniCodeRValue (right
, FALSE
),
4665 tree
->opval
.op
, tree
->ftype
);
4670 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4671 geniCodeRValue (right
, FALSE
),
4672 tree
->opval
.op
, tree
->ftype
);
4673 setOperandType (op
, UCHARTYPE
);
4678 operand
*op
= geniCodeBinary (geniCodeRValue (left
, FALSE
),
4679 geniCodeRValue (right
, FALSE
),
4680 tree
->opval
.op
, tree
->ftype
);
4681 setOperandType (op
, UINTTYPE
);
4686 return geniCodeLogicAndOr (tree
, lvl
);
4693 /* different compilers (even different gccs) evaluate
4694 the two calls in a different order. to get the same
4695 result on all machines we have to specify a clear sequence.
4696 return geniCodeLogic (geniCodeRValue (left, FALSE),
4697 geniCodeRValue (right, FALSE),
4701 operand
*leftOp
, *rightOp
;
4703 leftOp
= geniCodeRValue (left
, FALSE
);
4704 rightOp
= geniCodeRValue (right
, FALSE
);
4706 return geniCodeLogic (leftOp
, rightOp
, tree
->opval
.op
, tree
);
4709 return geniCodeConditional (tree
, lvl
);
4712 return operandFromLit (getSize (tree
->right
->ftype
));
4716 sym_link
*rtype
= operandType (right
);
4717 sym_link
*ltype
= operandType (left
);
4718 if (IS_PTR (rtype
) && IS_ITEMP (right
) && right
->isaddr
&& compareType (rtype
->next
, ltype
, false) == 1)
4719 right
= geniCodeRValue (right
, TRUE
);
4721 right
= geniCodeRValue (right
, FALSE
);
4722 return geniCodeAssign (left
, right
, 0, 1);
4726 geniCodeAssign (left
,
4727 geniCodeMultiply (geniCodeRValue (operandFromOperand (left
),
4729 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
4733 geniCodeAssign (left
,
4734 geniCodeDivision (geniCodeRValue (operandFromOperand (left
), FALSE
),
4735 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
), false), 0, 1);
4738 geniCodeAssign (left
,
4739 geniCodeModulus (geniCodeRValue (operandFromOperand (left
),
4741 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
4744 sym_link
*rtype
= operandType (right
);
4745 sym_link
*ltype
= operandType (left
);
4746 if (IS_PTR (rtype
) && IS_ITEMP (right
) && right
->isaddr
&& compareType (rtype
->next
, ltype
, false) == 1)
4747 right
= geniCodeRValue (right
, TRUE
);
4749 right
= geniCodeRValue (right
, FALSE
);
4752 return geniCodeAssign (left
,
4753 geniCodeAdd (geniCodeRValue (operandFromOperand (left
),
4754 FALSE
), right
, getResultTypeFromType (tree
->ftype
), lvl
), 0, 1);
4758 sym_link
*rtype
= operandType (right
);
4759 sym_link
*ltype
= operandType (left
);
4760 if (IS_PTR (rtype
) && IS_ITEMP (right
) && right
->isaddr
&& compareType (rtype
->next
, ltype
, false) == 1)
4762 right
= geniCodeRValue (right
, TRUE
);
4766 right
= geniCodeRValue (right
, FALSE
);
4769 geniCodeAssign (left
,
4770 geniCodeSubtract (geniCodeRValue (operandFromOperand (left
),
4771 FALSE
), right
, getResultTypeFromType (tree
->ftype
)), 0, 1);
4775 geniCodeAssign (left
,
4776 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left
), FALSE
),
4777 geniCodeRValue (right
, FALSE
), getResultTypeFromType (tree
->ftype
)), 0, 1);
4780 geniCodeAssign (left
,
4781 geniCodeRightShift (geniCodeRValue (operandFromOperand (left
), FALSE
),
4782 geniCodeRValue (right
, FALSE
)), 0, 1);
4785 geniCodeAssign (left
,
4786 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
),
4788 geniCodeRValue (right
, FALSE
), BITWISEAND
, operandType (left
)), 0, 1);
4791 geniCodeAssign (left
,
4792 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
),
4793 FALSE
), geniCodeRValue (right
, FALSE
), '^', operandType (left
)), 0, 1);
4796 geniCodeAssign (left
,
4797 geniCodeBitwise (geniCodeRValue (operandFromOperand (left
), FALSE
),
4798 geniCodeRValue (right
, FALSE
), '|', operandType (left
)), 0, 1);
4800 return geniCodeRValue (right
, FALSE
);
4803 return geniCodeCall (ast2iCode (tree
->left
, lvl
+ 1), tree
->right
, lvl
);
4806 geniCodeLabel (OP_SYMBOL (ast2iCode (tree
->left
, lvl
+ 1)));
4807 if (tree
->right
&& tree
->right
->type
== EX_VALUE
)
4809 geniCodeDummyRead (ast2iCode (tree
->right
, lvl
+ 1));
4813 return ast2iCode (tree
->right
, lvl
+ 1);
4816 geniCodeGoto (OP_SYMBOL (ast2iCode (tree
->left
, lvl
+ 1)));
4817 return ast2iCode (tree
->right
, lvl
+ 1);
4820 geniCodeFunctionBody (tree
, lvl
);
4824 geniCodeReturn (right
);
4828 geniCodeIfx (tree
, lvl
);
4832 geniCodeSwitch (tree
, lvl
);
4836 geniCodeInline (tree
);
4840 geniCodeArrayInit (tree
, ast2iCode (tree
->left
, lvl
+ 1));
4844 geniCodeCritical (tree
, lvl
);
4850 /*-----------------------------------------------------------------*/
4851 /* iCodeFromAst - given an ast will convert it to iCode */
4852 /*-----------------------------------------------------------------*/
4854 iCodeFromAst (ast
* tree
)
4856 returnLabel
= newiTempLabel ("_return");
4857 entryLabel
= newiTempLabel ("_entry");
4859 ast2iCode (tree
, 0);
4860 return (iCodeChain
);
4864 opTypeToStr (OPTYPE op
)
4875 return "undefined type";
4880 validateOpType (operand
*op
, const char *macro
, const char *args
, OPTYPE type
, const char *file
, unsigned line
)
4882 if (op
&& op
->type
== type
)
4887 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4888 " expected %s, got %s\n", macro
, args
, file
, line
, opTypeToStr (type
), op
? opTypeToStr (op
->type
) : "null op");
4889 exit (EXIT_FAILURE
);
4890 return op
; // never reached, makes compiler happy.
4894 validateOpTypeConst (const operand
*op
, const char *macro
, const char *args
, OPTYPE type
, const char *file
, unsigned line
)
4896 if (op
&& op
->type
== type
)
4901 "Internal error: validateOpTypeConst failed in %s(%s) @ %s:%u:"
4902 " expected %s, got %s\n", macro
, args
, file
, line
, opTypeToStr (type
), op
? opTypeToStr (op
->type
) : "null op");
4903 exit (EXIT_FAILURE
);
4904 return op
; // never reached, makes compiler happy.