04a3e055b2cd7c981cd9212a7be62038bdf25cf2
[fw/sdcc] / src / SDCCicode.c
1 /*-------------------------------------------------------------------------
2
3   SDCCicode.c - intermediate code generation etc.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
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.
15
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.
19
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 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include "newalloc.h"
27 #include "math.h"
28 #include "dbuf_string.h"
29
30 /*-----------------------------------------------------------------*/
31 /* global variables       */
32
33 set *iCodeChain = NULL;
34 int iTempNum = 0;
35 int iTempLblNum = 0;
36 int operandKey = 0;
37 int iCodeKey = 0;
38 char *filename;                 /* current file name */
39 int lineno = 1;                 /* current line number */
40 int block;
41 int scopeLevel;
42 int seqPoint;
43
44 symbol *returnLabel;            /* function return label */
45 symbol *entryLabel;             /* function entry  label */
46
47 /*-----------------------------------------------------------------*/
48 /* forward definition of some functions */
49 operand *geniCodeAssign (operand *, operand *, int, int);
50 static operand *geniCodeArray (operand *, operand *,int);
51 static operand *geniCodeArray2Ptr (operand *);
52 operand *geniCodeRValue (operand *, bool);
53 operand *geniCodeDerefPtr (operand *,int);
54 int isLvaluereq(int lvl);
55 void  setOClass (sym_link * ptr, sym_link * spec);
56 static operand *geniCodeCast (sym_link *, operand *, bool);
57
58 #define PRINTFUNC(x) void x (struct dbuf_s *dbuf, iCode *ic, char *s)
59 /* forward definition of ic print functions */
60 PRINTFUNC (picGetValueAtAddr);
61 PRINTFUNC (picSetValueAtAddr);
62 PRINTFUNC (picAddrOf);
63 PRINTFUNC (picGeneric);
64 PRINTFUNC (picGenericOne);
65 PRINTFUNC (picCast);
66 PRINTFUNC (picAssign);
67 PRINTFUNC (picLabel);
68 PRINTFUNC (picGoto);
69 PRINTFUNC (picIfx);
70 PRINTFUNC (picJumpTable);
71 PRINTFUNC (picInline);
72 PRINTFUNC (picReceive);
73 PRINTFUNC (picDummyRead);
74 PRINTFUNC (picCritical);
75 PRINTFUNC (picEndCritical);
76
77 iCodeTable codeTable[] =
78 {
79   {'!', "not", picGenericOne, NULL},
80   {'~', "~", picGenericOne, NULL},
81   {RRC, "rrc", picGenericOne, NULL},
82   {RLC, "rlc", picGenericOne, NULL},
83   {GETHBIT, "ghbit", picGenericOne, NULL},
84   {GETABIT, "gabit", picGenericOne, NULL},
85   {GETBYTE, "gbyte", picGenericOne, NULL},
86   {GETWORD, "gword", picGenericOne, NULL},
87   {UNARYMINUS, "-", picGenericOne, NULL},
88   {IPUSH, "push", picGenericOne, NULL},
89   {IPOP, "pop", picGenericOne, NULL},
90   {CALL, "call", picGenericOne, NULL},
91   {PCALL, "pcall", picGenericOne, NULL},
92   {FUNCTION, "proc", picGenericOne, NULL},
93   {ENDFUNCTION, "eproc", picGenericOne, NULL},
94   {RETURN, "ret", picGenericOne, NULL},
95   {'+', "+", picGeneric, NULL},
96   {'-', "-", picGeneric, NULL},
97   {'*', "*", picGeneric, NULL},
98   {'/', "/", picGeneric, NULL},
99   {'%', "%", picGeneric, NULL},
100   {'>', ">", picGeneric, NULL},
101   {'<', "<", picGeneric, NULL},
102   {LE_OP, "<=", picGeneric, NULL},
103   {GE_OP, ">=", picGeneric, NULL},
104   {EQ_OP, "==", picGeneric, NULL},
105   {NE_OP, "!=", picGeneric, NULL},
106   {AND_OP, "&&", picGeneric, NULL},
107   {OR_OP, "||", picGeneric, NULL},
108   {'^', "^", picGeneric, NULL},
109   {'|', "|", picGeneric, NULL},
110   {BITWISEAND, "&", picGeneric, NULL},
111   {LEFT_OP, "<<", picGeneric, NULL},
112   {RIGHT_OP, ">>", picGeneric, NULL},
113   {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
114   {ADDRESS_OF, "&", picAddrOf, NULL},
115   {CAST, "<>", picCast, NULL},
116   {'=', ":=", picAssign, NULL},
117   {LABEL, "", picLabel, NULL},
118   {GOTO, "", picGoto, NULL},
119   {JUMPTABLE, "jtab", picJumpTable, NULL},
120   {IFX, "if", picIfx, NULL},
121   {INLINEASM, "", picInline, NULL},
122   {RECEIVE, "recv", picReceive, NULL},
123   {SEND, "send", picGenericOne, NULL},
124   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
125   {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
126   {CRITICAL, "critical_start", picCritical, NULL},
127   {ENDCRITICAL, "critical_end", picEndCritical, NULL},
128   {SWAP, "swap", picGenericOne, NULL}
129 };
130
131 /*-----------------------------------------------------------------*/
132 /* operandName - returns the name of the operand                   */
133 /*-----------------------------------------------------------------*/
134 int
135 printOperand (operand * op, FILE * file)
136 {
137   struct dbuf_s dbuf;
138   int ret;
139   int pnl = 0;
140
141   if (!file)
142     {
143       file = stdout;
144       pnl = 1;
145     }
146   dbuf_init (&dbuf, 1024);
147   ret = dbuf_printOperand(op, &dbuf);
148   dbuf_write_and_destroy (&dbuf, file);
149
150   if (pnl)
151     putc ('\n', file);
152
153   return ret;
154 }
155
156 int
157 dbuf_printOperand (operand * op, struct dbuf_s *dbuf)
158 {
159   sym_link *opetype;
160
161   if (!op)
162     return 1;
163
164   switch (op->type)
165     {
166
167     case VALUE:
168       opetype = getSpec (operandType (op));
169       if (IS_FLOAT (opetype))
170         dbuf_printf (dbuf, "%g {", SPEC_CVAL (opetype).v_float);
171       else if (IS_FIXED16X16 (opetype))
172         dbuf_printf (dbuf, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
173       else
174         dbuf_printf (dbuf, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
175       dbuf_printTypeChain (operandType (op), dbuf);
176       dbuf_append_char (dbuf, '}');
177       break;
178
179     case SYMBOL:
180 #define REGA 1
181 //#if REGA      /* { */
182     if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
183       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}"  , */
184                (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
185                op->key,
186                OP_LIVEFROM (op), OP_LIVETO (op),
187                OP_SYMBOL (op)->stack,
188                op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
189                OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
190                OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
191         );
192       {
193         dbuf_append_char (dbuf, '{');
194         dbuf_printTypeChain (operandType (op), dbuf);
195         if (SPIL_LOC (op) && IS_ITEMP (op))
196           dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
197         dbuf_append_char (dbuf, '}');
198
199       }
200
201       /* if assigned to registers */
202       if (OP_SYMBOL (op)->nRegs)
203         {
204           if (OP_SYMBOL (op)->isspilt)
205             {
206               if (!OP_SYMBOL (op)->remat)
207                 if (OP_SYMBOL (op)->usl.spillLoc)
208                   dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
209                                        OP_SYMBOL (op)->usl.spillLoc->rname :
210                                        OP_SYMBOL (op)->usl.spillLoc->name));
211                 else
212                   dbuf_append_str (dbuf, "[err]");
213               else
214                 dbuf_append_str (dbuf, "[remat]");
215             }
216           else
217             {
218               int i;
219               dbuf_append_char (dbuf, '[');
220               for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
221                 dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
222               dbuf_append_char (dbuf, ']');
223             }
224         }
225 //#else         /* } else { */
226     } else {
227       /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
228       dbuf_printf (dbuf, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
229
230       if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
231         {
232           dbuf_printf (dbuf, "[lr%d:%d so:%d]",
233                OP_LIVEFROM (op), OP_LIVETO (op),
234                OP_SYMBOL (op)->stack);
235         }
236
237       if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
238         {
239           dbuf_append_char (dbuf, '{');
240           dbuf_printTypeChain (operandType (op), dbuf);
241           if (SPIL_LOC (op) && IS_ITEMP (op))
242               dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
243           dbuf_append_char (dbuf, '}');
244         }
245
246       /* if assigned to registers */
247       if (OP_SYMBOL (op)->nRegs)
248         {
249           if (OP_SYMBOL (op)->isspilt)
250             {
251               if (!OP_SYMBOL (op)->remat)
252                 if (OP_SYMBOL (op)->usl.spillLoc)
253                   dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
254                                        OP_SYMBOL (op)->usl.spillLoc->rname :
255                                        OP_SYMBOL (op)->usl.spillLoc->name));
256                 else
257                   dbuf_append_str (dbuf, "[err]");
258               else
259                 dbuf_append_str (dbuf, "[remat]");
260             }
261           else
262             {
263               int i;
264               dbuf_append_char (dbuf, '[');
265               for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
266                 dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
267               dbuf_append_char (dbuf, ']');
268             }
269         }
270 //#endif                /* } */
271     }
272       break;
273
274     case TYPE:
275       dbuf_append_char (dbuf, '(');
276       dbuf_printTypeChain (op->operand.typeOperand, dbuf);
277       dbuf_append_char (dbuf, ')');
278       break;
279     }
280
281   return 0;
282 }
283
284
285 /*-----------------------------------------------------------------*/
286 /*                    print functions                              */
287 /*-----------------------------------------------------------------*/
288 PRINTFUNC (picGetValueAtAddr)
289 {
290   dbuf_append_char (dbuf, '\t');
291   dbuf_printOperand (IC_RESULT (ic), dbuf);
292   dbuf_append_str (dbuf, " = ");
293   dbuf_append_str (dbuf, "@[");
294   dbuf_printOperand (IC_LEFT (ic), dbuf);
295   dbuf_append_str (dbuf, "]\n");
296 }
297
298 PRINTFUNC (picSetValueAtAddr)
299 {
300   dbuf_append_char (dbuf, '\t');
301   dbuf_append_str (dbuf, "*[");
302   dbuf_printOperand (IC_LEFT (ic), dbuf);
303   dbuf_append_str (dbuf, "] = ");
304   dbuf_printOperand (IC_RIGHT (ic), dbuf);
305   dbuf_append_char (dbuf, '\n');
306 }
307
308 PRINTFUNC (picAddrOf)
309 {
310   dbuf_append_char (dbuf, '\t');
311   dbuf_printOperand (IC_RESULT (ic), dbuf);
312   if (IS_ITEMP (IC_LEFT (ic)))
313     dbuf_append_str (dbuf, " = ");
314   else
315     dbuf_append_str (dbuf, " = &[");
316   dbuf_printOperand (IC_LEFT (ic), dbuf);
317   if (IC_RIGHT (ic))
318     {
319       if (IS_ITEMP (IC_LEFT (ic)))
320         dbuf_append_str (dbuf, " offsetAdd ");
321       else
322         dbuf_append_str (dbuf, " , ");
323       dbuf_printOperand (IC_RIGHT (ic), dbuf);
324     }
325   if (IS_ITEMP (IC_LEFT (ic)))
326     dbuf_append_char (dbuf, '\n');
327   else
328     dbuf_append_str (dbuf, "]\n");
329 }
330
331 PRINTFUNC (picJumpTable)
332 {
333   symbol *sym;
334
335   dbuf_append_char (dbuf, '\t');
336   dbuf_printf (dbuf, "%s\t", s);
337   dbuf_printOperand (IC_JTCOND (ic), dbuf);
338   for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
339        sym = setNextItem (IC_JTLABELS (ic)))
340     dbuf_printf (dbuf, "; %s", sym->name);
341   dbuf_append_char (dbuf, '\n');
342 }
343
344 PRINTFUNC (picGeneric)
345 {
346   dbuf_append_char (dbuf, '\t');
347   dbuf_printOperand (IC_RESULT (ic), dbuf);
348   dbuf_append_str (dbuf, " = ");
349   dbuf_printOperand (IC_LEFT (ic), dbuf);
350   dbuf_printf (dbuf, " %s ", s);
351   dbuf_printOperand (IC_RIGHT (ic), dbuf);
352   dbuf_append_char (dbuf, '\n');
353 }
354
355 PRINTFUNC (picGenericOne)
356 {
357   dbuf_append_char (dbuf, '\t');
358   if (IC_RESULT (ic))
359     {
360       dbuf_printOperand (IC_RESULT (ic), dbuf);
361       dbuf_append_str (dbuf, " = ");
362     }
363
364   if (IC_LEFT (ic))
365     {
366       dbuf_printf (dbuf, "%s ", s);
367       dbuf_printOperand (IC_LEFT (ic), dbuf);
368     }
369
370   if (!IC_RESULT (ic) && !IC_LEFT (ic))
371     dbuf_append_str (dbuf, s);
372
373   if (ic->op == SEND || ic->op == RECEIVE) {
374       dbuf_printf (dbuf,"{argreg = %d}",ic->argreg);
375   }
376   if (ic->op == IPUSH) {
377       dbuf_printf (dbuf,"{parmPush = %d}",ic->parmPush);
378   }
379   dbuf_append_char (dbuf, '\n');
380 }
381
382 PRINTFUNC (picCast)
383 {
384   dbuf_append_char (dbuf, '\t');
385   dbuf_printOperand (IC_RESULT (ic), dbuf);
386   dbuf_append_str (dbuf, " = ");
387   dbuf_printOperand (IC_LEFT (ic), dbuf);
388   dbuf_printOperand (IC_RIGHT (ic), dbuf);
389   dbuf_append_char (dbuf, '\n');
390 }
391
392
393 PRINTFUNC (picAssign)
394 {
395   dbuf_append_char (dbuf, '\t');
396
397   if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
398     dbuf_append_str (dbuf, "*(");
399
400   dbuf_printOperand (IC_RESULT (ic), dbuf);
401
402   if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
403     dbuf_append_char (dbuf, ')');
404
405   dbuf_printf (dbuf, " %s ", s);
406   dbuf_printOperand (IC_RIGHT (ic), dbuf);
407
408   dbuf_append_char (dbuf, '\n');
409 }
410
411 PRINTFUNC (picLabel)
412 {
413   dbuf_printf (dbuf, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
414 }
415
416 PRINTFUNC (picGoto)
417 {
418   dbuf_append_char (dbuf, '\t');
419   dbuf_printf (dbuf, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
420 }
421
422 PRINTFUNC (picIfx)
423 {
424   dbuf_append_char (dbuf, '\t');
425   dbuf_append_str (dbuf, "if ");
426   dbuf_printOperand (IC_COND (ic), dbuf);
427
428   if (!IC_TRUE (ic))
429     dbuf_printf (dbuf, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
430   else
431     {
432       dbuf_printf (dbuf, " != 0 goto %s($%d)", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
433       if (IC_FALSE (ic))
434         dbuf_printf (dbuf, "; zzgoto %s\n", IC_FALSE (ic)->name);
435       dbuf_append_char (dbuf, '\n');
436     }
437 }
438
439 PRINTFUNC (picInline)
440 {
441   dbuf_append_str (dbuf, IC_INLINE (ic));
442 }
443
444 PRINTFUNC (picReceive)
445 {
446   dbuf_printOperand (IC_RESULT (ic), dbuf);
447   dbuf_printf (dbuf, " = %s ", s);
448   dbuf_printOperand (IC_LEFT (ic), dbuf);
449   dbuf_append_char (dbuf, '\n');
450 }
451
452 PRINTFUNC (picDummyRead)
453 {
454   dbuf_append_char (dbuf, '\t');
455   dbuf_printf (dbuf, "%s ", s);
456   dbuf_printOperand (IC_RIGHT (ic), dbuf);
457   dbuf_append_char (dbuf, '\n');
458 }
459
460 PRINTFUNC (picCritical)
461 {
462   dbuf_append_char (dbuf, '\t');
463   if (IC_RESULT (ic))
464     dbuf_printOperand (IC_RESULT (ic), dbuf);
465   else
466     dbuf_append_str (dbuf, "(stack)");
467   dbuf_printf (dbuf, " = %s ", s);
468   dbuf_append_char (dbuf, '\n');
469 }
470
471 PRINTFUNC (picEndCritical)
472 {
473   dbuf_append_char (dbuf, '\t');
474   dbuf_printf (dbuf, "%s = ", s);
475   if (IC_RIGHT (ic))
476     dbuf_printOperand (IC_RIGHT (ic), dbuf);
477   else
478     dbuf_append_str (dbuf, "(stack)");
479   dbuf_append_char (dbuf, '\n');
480 }
481
482 /*-----------------------------------------------------------------*/
483 /* piCode - prints one iCode                                       */
484 /*-----------------------------------------------------------------*/
485 int
486 piCode (void *item, FILE * of)
487 {
488   iCode *ic = item;
489   iCodeTable *icTab;
490   struct dbuf_s dbuf;
491
492   if (!of)
493     of = stdout;
494
495   icTab = getTableEntry (ic->op);
496   fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
497            ic->filename, ic->lineno,
498            ic->seq, ic->key, ic->depth, ic->supportRtn);
499   dbuf_init (&dbuf, 1024);
500   icTab->iCodePrint (&dbuf, ic, icTab->printName);
501   dbuf_write_and_destroy (&dbuf, of);
502   return 1;
503 }
504
505 void PICC(iCode *ic)
506 {
507         printiCChain(ic,stdout);
508 }
509 /*-----------------------------------------------------------------*/
510 /* printiCChain - prints intermediate code for humans              */
511 /*-----------------------------------------------------------------*/
512 void
513 printiCChain (iCode * icChain, FILE * of)
514 {
515   iCode *loop;
516   iCodeTable *icTab;
517   struct dbuf_s dbuf;
518
519   if (!of)
520     of = stdout;
521   for (loop = icChain; loop; loop = loop->next)
522     {
523       if ((icTab = getTableEntry (loop->op)))
524         {
525           fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
526                    loop->filename, loop->lineno,
527                    loop->seq, loop->key, loop->depth, loop->supportRtn);
528
529           dbuf_init(&dbuf, 1024);
530           icTab->iCodePrint (&dbuf, loop, icTab->printName);
531           dbuf_write_and_destroy (&dbuf, of);
532           ////
533           fflush(of);
534         }
535     }
536 }
537
538
539 /*-----------------------------------------------------------------*/
540 /* newOperand - allocate, init & return a new iCode                */
541 /*-----------------------------------------------------------------*/
542 operand *
543 newOperand ()
544 {
545   operand *op;
546
547   op = Safe_alloc ( sizeof (operand));
548
549   op->key = 0;
550   return op;
551 }
552
553 /*-----------------------------------------------------------------*/
554 /* newiCode - create and return a new iCode entry initialised      */
555 /*-----------------------------------------------------------------*/
556 iCode *
557 newiCode (int op, operand * left, operand * right)
558 {
559   iCode *ic;
560
561   ic = Safe_alloc ( sizeof (iCode));
562
563   ic->seqPoint = seqPoint;
564   ic->lineno = lineno;
565   ic->filename = filename;
566   ic->block = block;
567   ic->level = scopeLevel;
568   ic->op = op;
569   ic->key = iCodeKey++;
570   IC_LEFT (ic) = left;
571   IC_RIGHT (ic) = right;
572
573   return ic;
574 }
575
576 /*-----------------------------------------------------------------*/
577 /* newiCode for conditional statements                             */
578 /*-----------------------------------------------------------------*/
579 iCode *
580 newiCodeCondition (operand * condition,
581                    symbol * trueLabel,
582                    symbol * falseLabel)
583 {
584   iCode *ic;
585
586   if (IS_VOID(operandType(condition))) {
587     werror(E_VOID_VALUE_USED);
588   }
589
590   ic = newiCode (IFX, NULL, NULL);
591   IC_COND (ic) = condition;
592   IC_TRUE (ic) = trueLabel;
593   IC_FALSE (ic) = falseLabel;
594   return ic;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* newiCodeLabelGoto - unconditional goto statement| label stmnt   */
599 /*-----------------------------------------------------------------*/
600 iCode *
601 newiCodeLabelGoto (int op, symbol * label)
602 {
603   iCode *ic;
604
605   ic = newiCode (op, NULL, NULL);
606   ic->op = op;
607   ic->label = label;
608   IC_LEFT (ic) = NULL;
609   IC_RIGHT (ic) = NULL;
610   IC_RESULT (ic) = NULL;
611   return ic;
612 }
613
614 /*-----------------------------------------------------------------*/
615 /* newiTemp - allocate & return a newItemp Variable                */
616 /*-----------------------------------------------------------------*/
617 symbol *
618 newiTemp (char *s)
619 {
620   symbol *itmp;
621
622   if (s)
623   {
624       SNPRINTF (buffer, sizeof(buffer), "%s", s);
625   }
626   else
627   {
628       SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
629   }
630
631   itmp = newSymbol (buffer, 1);
632   strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
633   itmp->isitmp = 1;
634
635   return itmp;
636 }
637
638 /*-----------------------------------------------------------------*/
639 /* newiTempLabel - creates a temp variable label                   */
640 /*-----------------------------------------------------------------*/
641 symbol *
642 newiTempLabel (char *s)
643 {
644   symbol *itmplbl;
645
646   /* check if this already exists */
647   if (s && (itmplbl = findSym (LabelTab, NULL, s)))
648     return itmplbl;
649
650   if (s)
651     {
652       itmplbl = newSymbol (s, 1);
653     }
654   else
655     {
656       SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
657       itmplbl = newSymbol (buffer, 1);
658     }
659
660   itmplbl->isitmp = 1;
661   itmplbl->islbl = 1;
662   itmplbl->key = labelKey++;
663   addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
664   return itmplbl;
665 }
666
667 /*-----------------------------------------------------------------*/
668 /* newiTempLoopHeaderLabel - creates a new loop header label       */
669 /*-----------------------------------------------------------------*/
670 symbol *
671 newiTempLoopHeaderLabel (bool pre)
672 {
673   symbol *itmplbl;
674
675   SNPRINTF (buffer, sizeof(buffer), pre ? "preHeaderLbl%d" : LOOPEXITLBL "%d",
676             iTempLblNum++);
677   itmplbl = newSymbol (buffer, 1);
678
679   itmplbl->isitmp = 1;
680   itmplbl->islbl = 1;
681   itmplbl->key = labelKey++;
682   addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
683   return itmplbl;
684 }
685
686
687 /*-----------------------------------------------------------------*/
688 /* initiCode - initialises some iCode related stuff                */
689 /*-----------------------------------------------------------------*/
690 void
691 initiCode ()
692 {
693
694 }
695
696 /*-----------------------------------------------------------------*/
697 /* copyiCode - make a copy of the iCode given                      */
698 /*-----------------------------------------------------------------*/
699 iCode *
700 copyiCode (iCode * ic)
701 {
702   iCode *nic = newiCode (ic->op, NULL, NULL);
703
704   nic->lineno = ic->lineno;
705   nic->filename = ic->filename;
706   nic->block = ic->block;
707   nic->level = ic->level;
708   nic->parmBytes = ic->parmBytes;
709
710   /* deal with the special cases first */
711   switch (ic->op)
712     {
713     case IFX:
714       IC_COND (nic) = operandFromOperand (IC_COND (ic));
715       IC_TRUE (nic) = IC_TRUE (ic);
716       IC_FALSE (nic) = IC_FALSE (ic);
717       break;
718
719     case JUMPTABLE:
720       IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
721       IC_JTLABELS (nic) = IC_JTLABELS (ic);
722       break;
723
724     case CALL:
725     case PCALL:
726       IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
727       IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
728       break;
729
730     case INLINEASM:
731       IC_INLINE (nic) = IC_INLINE (ic);
732       break;
733
734     case ARRAYINIT:
735       IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
736       break;
737
738     default:
739       IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
740       IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
741       IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
742     }
743
744   return nic;
745 }
746
747 /*-----------------------------------------------------------------*/
748 /* getTableEntry - gets the table entry for the given operator     */
749 /*-----------------------------------------------------------------*/
750 iCodeTable *
751 getTableEntry (int oper)
752 {
753   unsigned i;
754
755   for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
756     if (oper == codeTable[i].icode)
757       return &codeTable[i];
758
759   return NULL;
760 }
761
762 /*-----------------------------------------------------------------*/
763 /* newiTempOperand - new intermediate temp operand                 */
764 /*-----------------------------------------------------------------*/
765 operand *
766 newiTempOperand (sym_link * type, char throwType)
767 {
768   symbol *itmp;
769   operand *op = newOperand ();
770   sym_link *etype;
771
772   op->type = SYMBOL;
773   itmp = newiTemp (NULL);
774
775   etype = getSpec (type);
776
777   if (IS_LITERAL (etype))
778     throwType = 0;
779
780   /* copy the type information */
781   if (type)
782     itmp->etype = getSpec (itmp->type = (throwType ? type :
783                                          copyLinkChain (type)));
784   if (IS_LITERAL (itmp->etype))
785     {
786       SPEC_SCLS (itmp->etype) = S_REGISTER;
787       SPEC_OCLS (itmp->etype) = reg;
788     }
789
790   op->operand.symOperand = itmp;
791   op->key = itmp->key = ++operandKey;
792   return op;
793 }
794
795 /*-----------------------------------------------------------------*/
796 /* operandType - returns the type chain for an operand             */
797 /*-----------------------------------------------------------------*/
798 sym_link *
799 operandType (operand * op)
800 {
801   /* depending on type of operand */
802   switch (op->type)
803     {
804
805     case VALUE:
806       return op->operand.valOperand->type;
807
808     case SYMBOL:
809       return op->operand.symOperand->type;
810
811     case TYPE:
812       return op->operand.typeOperand;
813     default:
814       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
815               " operand type not known ");
816       assert (0);               /* should never come here */
817       /*  Just to keep the compiler happy */
818       return (sym_link *) 0;
819     }
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* isParamterToCall - will return 1 if op is a parameter to args   */
824 /*-----------------------------------------------------------------*/
825 int
826 isParameterToCall (value * args, operand * op)
827 {
828   value *tval = args;
829
830   wassert (IS_SYMOP(op));
831
832   while (tval)
833     {
834       if (tval->sym &&
835           isSymbolEqual (op->operand.symOperand, tval->sym))
836         return 1;
837       tval = tval->next;
838     }
839   return 0;
840 }
841
842 /*-----------------------------------------------------------------*/
843 /* isOperandGlobal   - return 1 if operand is a global variable    */
844 /*-----------------------------------------------------------------*/
845 int
846 isOperandGlobal (operand * op)
847 {
848   if (!op)
849     return 0;
850
851   if (IS_ITEMP (op))
852     return 0;
853
854   if (IS_SYMOP(op) &&
855       (op->operand.symOperand->level == 0 ||
856        IS_STATIC (op->operand.symOperand->etype) ||
857        IS_EXTERN (op->operand.symOperand->etype))
858     )
859     return 1;
860
861   return 0;
862 }
863
864 /*-----------------------------------------------------------------*/
865 /* isOperandVolatile - return 1 if the operand is volatile         */
866 /*-----------------------------------------------------------------*/
867 int
868 isOperandVolatile (operand * op, bool chkTemp)
869 {
870   sym_link *optype;
871   sym_link *opetype;
872
873   if (IS_ITEMP (op) && !chkTemp)
874     return 0;
875
876   opetype = getSpec (optype = operandType (op));
877
878   if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
879     return 1;
880
881   if (IS_VOLATILE (opetype))
882     return 1;
883   return 0;
884 }
885
886 /*-----------------------------------------------------------------*/
887 /* isOperandLiteral - returns 1 if an operand contains a literal   */
888 /*-----------------------------------------------------------------*/
889 int
890 isOperandLiteral (operand * op)
891 {
892   sym_link *opetype;
893
894   if (!op)
895     return 0;
896
897   opetype = getSpec (operandType (op));
898
899   if (IS_LITERAL (opetype))
900     return 1;
901
902   return 0;
903 }
904
905 /*-----------------------------------------------------------------*/
906 /* isOperandInFarSpace - will return true if operand is in farSpace */
907 /*-----------------------------------------------------------------*/
908 bool
909 isOperandInFarSpace (operand * op)
910 {
911   sym_link *etype;
912
913   if (!op)
914     return FALSE;
915
916   if (!IS_SYMOP (op))
917     return FALSE;
918
919   if (!IS_TRUE_SYMOP (op))
920     {
921       if (SPIL_LOC (op))
922         etype = SPIL_LOC (op)->etype;
923       else
924         return FALSE;
925     }
926   else
927     {
928       etype = getSpec (operandType (op));
929     }
930   return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
931 }
932
933 /*-----------------------------------------------------------------*/
934 /* isOperandInPagedSpace - return true if operand is in pagedSpace */
935 /*-----------------------------------------------------------------*/
936 bool
937 isOperandInPagedSpace (operand * op)
938 {
939   sym_link *etype;
940
941   if (!op)
942     return FALSE;
943
944   if (!IS_SYMOP (op))
945     return FALSE;
946
947   if (!IS_TRUE_SYMOP (op))
948     {
949       if (SPIL_LOC (op))
950         etype = SPIL_LOC (op)->etype;
951       else
952         return FALSE;
953     }
954   else
955     {
956       etype = getSpec (operandType (op));
957     }
958   return (IN_PAGEDSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
959 }
960
961 /*------------------------------------------------------------------*/
962 /* isOperandInDirSpace - will return true if operand is in dirSpace */
963 /*------------------------------------------------------------------*/
964 bool
965 isOperandInDirSpace (operand * op)
966 {
967   sym_link *etype;
968
969   if (!op)
970     return FALSE;
971
972   if (!IS_SYMOP (op))
973     return FALSE;
974
975   if (!IS_TRUE_SYMOP (op))
976     {
977       if (SPIL_LOC (op))
978         etype = SPIL_LOC (op)->etype;
979       else
980         return FALSE;
981     }
982   else
983     {
984       etype = getSpec (operandType (op));
985     }
986   return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
987 }
988
989 /*--------------------------------------------------------------------*/
990 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
991 /*--------------------------------------------------------------------*/
992 bool
993 isOperandInCodeSpace (operand * op)
994 {
995   sym_link *etype;
996
997   if (!op)
998     return FALSE;
999
1000   if (!IS_SYMOP (op))
1001     return FALSE;
1002
1003   etype = getSpec (operandType (op));
1004
1005   if (!IS_TRUE_SYMOP (op))
1006     {
1007       if (SPIL_LOC (op))
1008         etype = SPIL_LOC (op)->etype;
1009       else
1010         return FALSE;
1011     }
1012   else
1013     {
1014       etype = getSpec (operandType (op));
1015     }
1016   return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* isOperandOnStack - will return true if operand is on stack      */
1021 /*-----------------------------------------------------------------*/
1022 bool
1023 isOperandOnStack (operand * op)
1024 {
1025   sym_link *etype;
1026
1027   if (!op)
1028     return FALSE;
1029
1030   if (!IS_SYMOP (op))
1031     return FALSE;
1032
1033   etype = getSpec (operandType (op));
1034   if (IN_STACK (etype) ||
1035       OP_SYMBOL(op)->onStack ||
1036       (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
1037     return TRUE;
1038
1039   return FALSE;
1040 }
1041
1042 /*-----------------------------------------------------------------*/
1043 /* isOclsExpensive - will return true if accesses to an output     */
1044 /*                   storage class are expensive                   */
1045 /*-----------------------------------------------------------------*/
1046 bool
1047 isOclsExpensive (struct memmap *oclass)
1048 {
1049   if (port->oclsExpense)
1050     return port->oclsExpense (oclass) > 0;
1051
1052   /* In the absence of port specific guidance, assume only */
1053   /* farspace is expensive. */
1054   return IN_FARSPACE (oclass);
1055 }
1056
1057 /*-----------------------------------------------------------------*/
1058 /* isiCodeInFunctionCall - return TRUE if an iCode is between a    */
1059 /*   CALL/PCALL and the first IPUSH/SEND associated with the call  */
1060 /*-----------------------------------------------------------------*/
1061 int
1062 isiCodeInFunctionCall (iCode * ic)
1063 {
1064   iCode * lic = ic;
1065
1066   /* Find the next CALL/PCALL */
1067   while (lic)
1068     {
1069       if (lic->op == CALL || lic->op == PCALL)
1070         break;
1071       lic = lic->next;
1072     }
1073
1074   if (!lic)
1075     return FALSE;
1076
1077   /* A function call was found. Scan backwards and see if an */
1078   /* IPUSH or SEND is encountered */
1079   while (ic)
1080     {
1081       if (lic != ic && (ic->op == CALL || ic->op == PCALL))
1082         return FALSE;
1083       if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
1084         return TRUE;
1085       ic = ic->prev;
1086     }
1087
1088   return FALSE;
1089 }
1090
1091 /*-----------------------------------------------------------------*/
1092 /* operandLitValue - literal value of an operand                   */
1093 /*-----------------------------------------------------------------*/
1094 double
1095 operandLitValue (operand * op)
1096 {
1097   assert (isOperandLiteral (op));
1098
1099   return floatFromVal (op->operand.valOperand);
1100 }
1101
1102 /*-----------------------------------------------------------------*/
1103 /* getBuiltInParms - returns parameters to a builtin functions     */
1104 /*-----------------------------------------------------------------*/
1105 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1106 {
1107     sym_link *ftype;
1108
1109     *pcount = 0;
1110     /* builtin functions uses only SEND for parameters */
1111     while (ic->op != CALL) {
1112         assert(ic->op == SEND && ic->builtinSEND);
1113         ic->generated = 1;    /* mark the icode as generated */
1114         parms[*pcount] = IC_LEFT(ic);
1115         ic = ic->next;
1116         (*pcount)++;
1117     }
1118
1119     ic->generated = 1;
1120     /* make sure this is a builtin function call */
1121     assert(IS_SYMOP(IC_LEFT(ic)));
1122     ftype = operandType(IC_LEFT(ic));
1123     assert(IFFUNC_ISBUILTIN(ftype));
1124     return ic;
1125 }
1126
1127 /*-----------------------------------------------------------------*/
1128 /* operandOperation - performs operations on operands             */
1129 /*-----------------------------------------------------------------*/
1130 operand *
1131 operandOperation (operand * left, operand * right,
1132                   int op, sym_link * type)
1133 {
1134   sym_link *let , *ret=NULL;
1135   operand *retval = (operand *) 0;
1136
1137   assert (isOperandLiteral (left));
1138   let = getSpec(operandType(left));
1139   if (right) {
1140     assert (isOperandLiteral (right));
1141     ret = getSpec(operandType(right));
1142   }
1143
1144   switch (op)
1145     {
1146     case '+':
1147       retval = operandFromValue (valCastLiteral (type,
1148                                                  operandLitValue (left) +
1149                                                  operandLitValue (right)));
1150       break;
1151     case '-':
1152       retval = operandFromValue (valCastLiteral (type,
1153                                                  operandLitValue (left) -
1154                                                  operandLitValue (right)));
1155       break;
1156     case '*':
1157       /*
1158       retval = operandFromValue (valCastLiteral (type,
1159                                                  operandLitValue (left) *
1160                                                  operandLitValue (right)));
1161       This could be all we've to do, but with gcc we've to take care about
1162       overflows. Two examples:
1163       ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
1164       significant bits are lost (52 in fraction, 63 bits would be
1165       necessary to keep full precision).
1166       If the resulting double value is greater than ULONG_MAX (resp.
1167       USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
1168       */
1169
1170       /* if it is not a specifier then we can assume that */
1171       /* it will be an unsigned long                      */
1172       if (IS_INT (type) ||
1173           !IS_SPEC (type))
1174         {
1175           /* long is handled here, because it can overflow with double */
1176           if (IS_LONG (type) ||
1177               !IS_SPEC (type))
1178           /* signed and unsigned mul are the same, as long as the precision
1179              of the result isn't bigger than the precision of the operands. */
1180             retval = operandFromValue (valCastLiteral (type,
1181                      (TYPE_TARGET_ULONG) operandLitValue (left) *
1182                      (TYPE_TARGET_ULONG) operandLitValue (right)));
1183           else if (IS_UNSIGNED (type)) /* unsigned int */
1184             {
1185               /* unsigned int is handled here in order to detect overflow */
1186               TYPE_TARGET_ULONG ul = (TYPE_TARGET_UINT) operandLitValue (left) *
1187                                      (TYPE_TARGET_UINT) operandLitValue (right);
1188
1189               retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_UINT) ul));
1190               if (ul != (TYPE_TARGET_UINT) ul)
1191                 werror (W_INT_OVL);
1192             }
1193           else /* signed int */
1194             {
1195               /* signed int is handled here in order to detect overflow */
1196               TYPE_TARGET_LONG l = (TYPE_TARGET_INT) operandLitValue (left) *
1197                                    (TYPE_TARGET_INT) operandLitValue (right);
1198
1199               retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_INT) l));
1200               if (l != (TYPE_TARGET_INT) l)
1201                 werror (W_INT_OVL);
1202             }
1203         }
1204       else
1205         /* all others go here: */
1206         retval = operandFromValue (valCastLiteral (type,
1207                                                    operandLitValue (left) *
1208                                                    operandLitValue (right)));
1209       break;
1210     case '/':
1211       if ((TYPE_TARGET_ULONG) operandLitValue (right) == 0)
1212         {
1213           werror (E_DIVIDE_BY_ZERO);
1214           retval = right;
1215
1216         }
1217       else
1218         {
1219           if (IS_UNSIGNED (type))
1220             {
1221               SPEC_USIGN (let) = 1;
1222               SPEC_USIGN (ret) = 1;
1223               retval = operandFromValue (valCastLiteral (type,
1224                                         (TYPE_TARGET_ULONG) operandLitValue (left) /
1225                                         (TYPE_TARGET_ULONG) operandLitValue (right)));
1226             }
1227           else
1228             {
1229               retval = operandFromValue (valCastLiteral (type,
1230                                                      operandLitValue (left) /
1231                                                      operandLitValue (right)));
1232             }
1233         }
1234       break;
1235     case '%':
1236       if ((TYPE_TARGET_ULONG) operandLitValue (right) == 0)
1237         {
1238           werror (E_DIVIDE_BY_ZERO);
1239           retval = right;
1240         }
1241       else
1242         {
1243           if (IS_UNSIGNED (type))
1244             retval = operandFromLit ((TYPE_TARGET_ULONG) operandLitValue (left) %
1245                                      (TYPE_TARGET_ULONG) operandLitValue (right));
1246           else
1247             retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) %
1248                                      (TYPE_TARGET_LONG) operandLitValue (right));
1249         }
1250       break;
1251     case LEFT_OP:
1252       /* The number of left shifts is always unsigned. Signed doesn't make
1253          sense here. Shifting by a negative number is impossible. */
1254       retval = operandFromValue (valCastLiteral (type,
1255                                  ((TYPE_TARGET_ULONG) operandLitValue (left) <<
1256                                   (TYPE_TARGET_ULONG) operandLitValue (right))));
1257       break;
1258     case RIGHT_OP:
1259       /* The number of right shifts is always unsigned. Signed doesn't make
1260          sense here. Shifting by a negative number is impossible. */
1261       if (IS_UNSIGNED(let))
1262         /* unsigned: logic shift right */
1263         retval = operandFromLit ((TYPE_TARGET_ULONG) operandLitValue (left) >>
1264                                  (TYPE_TARGET_ULONG) operandLitValue (right));
1265       else
1266         /* signed: arithmetic shift right */
1267         retval = operandFromLit ((TYPE_TARGET_LONG ) operandLitValue (left) >>
1268                                  (TYPE_TARGET_ULONG) operandLitValue (right));
1269       break;
1270     case EQ_OP:
1271       if (IS_FLOAT (let) || IS_FLOAT (ret))
1272         {
1273           retval = operandFromLit (operandLitValue (left) ==
1274                                    operandLitValue (right));
1275         }
1276       else if (IS_FIXED16X16 (let) || IS_FIXED16X16 (ret))
1277         {
1278           retval = operandFromLit (operandLitValue (left) ==
1279                                    operandLitValue (right));
1280         }
1281       else
1282         {
1283           /* this op doesn't care about signedness */
1284           TYPE_TARGET_ULONG l, r;
1285
1286           l = (TYPE_TARGET_ULONG) operandLitValue (left);
1287           r = (TYPE_TARGET_ULONG) operandLitValue (right);
1288           /* In order to correctly compare 'signed int' and 'unsigned int' it's
1289              neccessary to strip them to 16 bit.
1290              Literals are reduced to their cheapest type, therefore left and
1291              right might have different types. It's neccessary to find a
1292              common type: int (used for char too) or long */
1293           if (!IS_LONG (let) &&
1294               !IS_LONG (ret))
1295             {
1296               r = (TYPE_TARGET_UINT) r;
1297               l = (TYPE_TARGET_UINT) l;
1298             }
1299           retval = operandFromLit (l == r);
1300         }
1301       break;
1302     case '<':
1303       retval = operandFromLit (operandLitValue (left) <
1304                                operandLitValue (right));
1305       break;
1306     case LE_OP:
1307       retval = operandFromLit (operandLitValue (left) <=
1308                                operandLitValue (right));
1309       break;
1310     case NE_OP:
1311       retval = operandFromLit (operandLitValue (left) !=
1312                                operandLitValue (right));
1313       break;
1314     case '>':
1315       retval = operandFromLit (operandLitValue (left) >
1316                                operandLitValue (right));
1317       break;
1318     case GE_OP:
1319       retval = operandFromLit (operandLitValue (left) >=
1320                                operandLitValue (right));
1321       break;
1322     case BITWISEAND:
1323       retval = operandFromValue (valCastLiteral (type,
1324                                                  (TYPE_TARGET_ULONG)operandLitValue(left) &
1325                                                  (TYPE_TARGET_ULONG)operandLitValue(right)));
1326       break;
1327     case '|':
1328       retval = operandFromValue (valCastLiteral (type,
1329                                                  (TYPE_TARGET_ULONG)operandLitValue(left) |
1330                                                  (TYPE_TARGET_ULONG)operandLitValue(right)));
1331       break;
1332     case '^':
1333       retval = operandFromValue (valCastLiteral (type,
1334                                                  (TYPE_TARGET_ULONG)operandLitValue(left) ^
1335                                                  (TYPE_TARGET_ULONG)operandLitValue(right)));
1336       break;
1337     case AND_OP:
1338       retval = operandFromLit (operandLitValue (left) &&
1339                                operandLitValue (right));
1340       break;
1341     case OR_OP:
1342       retval = operandFromLit (operandLitValue (left) ||
1343                                operandLitValue (right));
1344       break;
1345     case RRC:
1346       {
1347         TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) operandLitValue (left);
1348
1349         retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1350                                  (i << 1));
1351       }
1352       break;
1353     case RLC:
1354       {
1355         TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) operandLitValue (left);
1356
1357         retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1358                                  (i >> 1));
1359       }
1360       break;
1361     case GETABIT:
1362       retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1363                                 (TYPE_TARGET_ULONG)operandLitValue(right)) & 1);
1364       break;
1365     case GETBYTE:
1366       retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1367                                 (TYPE_TARGET_ULONG)operandLitValue(right)) & 0xFF);
1368       break;
1369     case GETWORD:
1370       retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1371                                 (TYPE_TARGET_ULONG)operandLitValue(right)) & 0xFFFF);
1372       break;
1373
1374     case GETHBIT:
1375       retval = operandFromLit (((TYPE_TARGET_ULONG)operandLitValue(left) >>
1376                                 ((getSize (let) * 8) - 1)) & 1);
1377       break;
1378
1379     case UNARYMINUS:
1380       retval = operandFromValue (valCastLiteral (type,
1381                                                  -1 * operandLitValue (left)));
1382       break;
1383
1384     case '~':
1385       retval = operandFromValue (valCastLiteral (type,
1386                                                  ~((TYPE_TARGET_ULONG)
1387                                                    operandLitValue (left))));
1388       break;
1389
1390     case '!':
1391       retval = operandFromLit (!operandLitValue (left));
1392       break;
1393
1394     default:
1395       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1396               " operandOperation invalid operator ");
1397       assert (0);
1398     }
1399
1400   return retval;
1401 }
1402
1403
1404 /*-----------------------------------------------------------------*/
1405 /* isOperandEqual - compares two operand & return 1 if they r =    */
1406 /*-----------------------------------------------------------------*/
1407 int
1408 isOperandEqual (operand * left, operand * right)
1409 {
1410   /* if the pointers are equal then they are equal */
1411   if (left == right)
1412     return 1;
1413
1414   /* if either of them null then false */
1415   if (!left || !right)
1416     return 0;
1417
1418   if (left->type != right->type)
1419     return 0;
1420
1421   if (IS_SYMOP (left) && IS_SYMOP (right))
1422     return left->key == right->key;
1423
1424   /* if types are the same */
1425   switch (left->type)
1426     {
1427     case SYMBOL:
1428       return isSymbolEqual (left->operand.symOperand,
1429                             right->operand.symOperand);
1430     case VALUE:
1431       return (compareType (left->operand.valOperand->type,
1432                            right->operand.valOperand->type) &&
1433               (floatFromVal (left->operand.valOperand) ==
1434                floatFromVal (right->operand.valOperand)));
1435     case TYPE:
1436       if (compareType (left->operand.typeOperand,
1437                      right->operand.typeOperand) == 1)
1438         return 1;
1439     }
1440
1441   return 0;
1442 }
1443
1444 /*-------------------------------------------------------------------*/
1445 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1446 /*-------------------------------------------------------------------*/
1447 int
1448 isiCodeEqual (iCode * left, iCode * right)
1449 {
1450   /* if the same pointer */
1451   if (left == right)
1452     return 1;
1453
1454   /* if either of them null */
1455   if (!left || !right)
1456     return 0;
1457
1458   /* if operand are the same */
1459   if (left->op == right->op)
1460     {
1461
1462       /* compare all the elements depending on type */
1463       if (left->op != IFX)
1464         {
1465           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1466             return 0;
1467           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1468             return 0;
1469
1470         }
1471       else
1472         {
1473           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1474             return 0;
1475           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1476             return 0;
1477           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1478             return 0;
1479         }
1480
1481       return 1;
1482     }
1483   return 0;
1484 }
1485
1486 /*-----------------------------------------------------------------*/
1487 /* newiTempFromOp - create a temp Operand with same attributes     */
1488 /*-----------------------------------------------------------------*/
1489 operand *
1490 newiTempFromOp (operand * op)
1491 {
1492   operand *nop;
1493
1494   if (!op)
1495     return NULL;
1496
1497   if (!IS_ITEMP (op))
1498     return op;
1499
1500   nop = newiTempOperand (operandType (op), TRUE);
1501   nop->isaddr = op->isaddr;
1502   nop->isvolatile = op->isvolatile;
1503   nop->isGlobal = op->isGlobal;
1504   nop->isLiteral = op->isLiteral;
1505   nop->usesDefs = op->usesDefs;
1506   nop->isParm = op->isParm;
1507   return nop;
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* operand from operand - creates an operand holder for the type   */
1512 /*-----------------------------------------------------------------*/
1513 operand *
1514 operandFromOperand (operand * op)
1515 {
1516   operand *nop;
1517
1518   if (!op)
1519     return NULL;
1520   nop = newOperand ();
1521   nop->type = op->type;
1522   nop->isaddr = op->isaddr;
1523   nop->key = op->key;
1524   nop->isvolatile = op->isvolatile;
1525   nop->isGlobal = op->isGlobal;
1526   nop->isLiteral = op->isLiteral;
1527   nop->usesDefs = op->usesDefs;
1528   nop->isParm = op->isParm;
1529
1530   switch (nop->type)
1531     {
1532     case SYMBOL:
1533       nop->operand.symOperand = op->operand.symOperand;
1534       break;
1535     case VALUE:
1536       nop->operand.valOperand = op->operand.valOperand;
1537       break;
1538     case TYPE:
1539       nop->operand.typeOperand = op->operand.typeOperand;
1540       break;
1541     }
1542
1543   return nop;
1544 }
1545
1546 /*-----------------------------------------------------------------*/
1547 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1548 /*-----------------------------------------------------------------*/
1549 operand *
1550 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1551 {
1552   operand *nop = operandFromOperand (op);
1553
1554   if (nop->type == SYMBOL)
1555     {
1556       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1557       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1558     }
1559
1560   return nop;
1561 }
1562
1563 /*-----------------------------------------------------------------*/
1564 /* operandFromSymbol - creates an operand from a symbol            */
1565 /*-----------------------------------------------------------------*/
1566 operand *
1567 operandFromSymbol (symbol * sym)
1568 {
1569   operand *op;
1570   iCode *ic;
1571   int ok = 1;
1572   /* if the symbol's type is a literal */
1573   /* then it is an enumerator type     */
1574   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1575     return operandFromValue (valFromType (sym->etype));
1576
1577   if (!sym->key)
1578     sym->key = ++operandKey;
1579
1580   /* if this an implicit variable, means struct/union */
1581   /* member so just return it                         */
1582   if (sym->implicit || IS_FUNC (sym->type))
1583     {
1584       op = newOperand ();
1585       op->type = SYMBOL;
1586       op->operand.symOperand = sym;
1587       op->key = sym->key;
1588       op->isvolatile = isOperandVolatile (op, TRUE);
1589       op->isGlobal = isOperandGlobal (op);
1590       return op;
1591     }
1592
1593   /* under the following conditions create a
1594      register equivalent for a local symbol */
1595   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1596       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1597       !TARGET_IS_HC08 &&
1598       (!(options.model == MODEL_FLAT24)) ) &&
1599       options.stackAuto == 0)
1600     ok = 0;
1601
1602   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1603       !IS_FUNC (sym->type) &&           /* not a function   */
1604       !sym->_isparm &&                  /* not a parameter  */
1605       IS_AUTO (sym) &&                  /* is a local auto variable */
1606       !sym->addrtaken &&                /* whose address has not been taken */
1607       !sym->reqv &&                     /* does not already have a reg equivalence */
1608       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1609       !sym->islbl &&                    /* not a label */
1610       ok                            /* farspace check */
1611     )
1612     {
1613
1614       /* we will use it after all optimizations
1615          and before liveRange calculation */
1616       sym->reqv = newiTempOperand (sym->type, 0);
1617       sym->reqv->key = sym->key;
1618       OP_SYMBOL (sym->reqv)->prereqv = sym;
1619       OP_SYMBOL (sym->reqv)->key = sym->key;
1620       OP_SYMBOL (sym->reqv)->isreqv = 1;
1621       OP_SYMBOL (sym->reqv)->islocal = 1;
1622       OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1623       SPIL_LOC (sym->reqv) = sym;
1624     }
1625
1626   if (!IS_AGGREGATE (sym->type))
1627     {
1628       op = newOperand ();
1629       op->type = SYMBOL;
1630       op->operand.symOperand = sym;
1631       op->isaddr = 1;
1632       op->key = sym->key;
1633       op->isvolatile = isOperandVolatile (op, TRUE);
1634       op->isGlobal = isOperandGlobal (op);
1635       op->isPtr = IS_PTR (operandType (op));
1636       op->isParm = sym->_isparm;
1637       return op;
1638     }
1639
1640   /* create :-                     */
1641   /*    itemp = &[_symbol]         */
1642
1643   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1644   IC_LEFT (ic)->type = SYMBOL;
1645   IC_LEFT (ic)->operand.symOperand = sym;
1646   IC_LEFT (ic)->key = sym->key;
1647   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1648   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1649   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1650
1651   /* create result */
1652   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1653   if (IS_ARRAY (sym->type))
1654     {
1655       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1656       IC_RESULT (ic)->isaddr = 0;
1657     }
1658   else
1659     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1660
1661   ADDTOCHAIN (ic);
1662
1663   return IC_RESULT (ic);
1664 }
1665
1666 /*-----------------------------------------------------------------*/
1667 /* operandFromValue - creates an operand from value                */
1668 /*-----------------------------------------------------------------*/
1669 operand *
1670 operandFromValue (value * val)
1671 {
1672   operand *op;
1673
1674   /* if this is a symbol then do the symbol thing */
1675   if (val->sym)
1676     return operandFromSymbol (val->sym);
1677
1678   /* this is not a symbol */
1679   op = newOperand ();
1680   op->type = VALUE;
1681   op->operand.valOperand = val;
1682   op->isLiteral = isOperandLiteral (op);
1683   return op;
1684 }
1685
1686 /*-----------------------------------------------------------------*/
1687 /* operandFromLink - operand from typeChain                        */
1688 /*-----------------------------------------------------------------*/
1689 operand *
1690 operandFromLink (sym_link * type)
1691 {
1692   operand *op;
1693
1694   /* operand from sym_link */
1695   if (!type)
1696     return NULL;
1697
1698   op = newOperand ();
1699   op->type = TYPE;
1700   op->operand.typeOperand = copyLinkChain (type);
1701   return op;
1702 }
1703
1704 /*-----------------------------------------------------------------*/
1705 /* operandFromLit - makes an operand from a literal value          */
1706 /*-----------------------------------------------------------------*/
1707 operand *
1708 operandFromLit (double i)
1709 {
1710   return operandFromValue (valueFromLit (i));
1711 }
1712
1713 /*-----------------------------------------------------------------*/
1714 /* operandFromAst - creates an operand from an ast                 */
1715 /*-----------------------------------------------------------------*/
1716 operand *
1717 operandFromAst (ast * tree,int lvl)
1718 {
1719
1720   if (!tree)
1721     return NULL;
1722
1723   /* depending on type do */
1724   switch (tree->type)
1725     {
1726     case EX_OP:
1727       return ast2iCode (tree,lvl+1);
1728       break;
1729
1730     case EX_VALUE:
1731       return operandFromValue (tree->opval.val);
1732       break;
1733
1734     case EX_LINK:
1735       return operandFromLink (tree->opval.lnk);
1736       break;
1737
1738     default:
1739       assert (0);
1740     }
1741
1742   /*  Just to keep the compiler happy */
1743   return (operand *) 0;
1744 }
1745
1746 /*-----------------------------------------------------------------*/
1747 /* setOperandType - sets the operand's type to the given type      */
1748 /*-----------------------------------------------------------------*/
1749 void
1750 setOperandType (operand * op, sym_link * type)
1751 {
1752   /* depending on the type of operand */
1753   switch (op->type)
1754     {
1755
1756     case VALUE:
1757       op->operand.valOperand->etype =
1758         getSpec (op->operand.valOperand->type =
1759                  copyLinkChain (type));
1760       return;
1761
1762     case SYMBOL:
1763       if (op->operand.symOperand->isitmp)
1764         op->operand.symOperand->etype =
1765           getSpec (op->operand.symOperand->type =
1766                    copyLinkChain (type));
1767       else
1768         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1769                 "attempt to modify type of source");
1770       return;
1771
1772     case TYPE:
1773       op->operand.typeOperand = copyLinkChain (type);
1774       return;
1775     }
1776
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* Get size in byte of ptr need to access an array                 */
1781 /*-----------------------------------------------------------------*/
1782 static unsigned int
1783 getArraySizePtr (operand * op)
1784 {
1785   sym_link *ltype = operandType(op);
1786
1787   if(IS_PTR(ltype))
1788     {
1789       int size = getSize(ltype);
1790       return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1791     }
1792
1793   if(IS_ARRAY(ltype))
1794     {
1795       sym_link *letype = getSpec(ltype);
1796       switch (PTR_TYPE (SPEC_OCLS (letype)))
1797         {
1798         case IPOINTER:
1799         case PPOINTER:
1800         case POINTER:
1801           return (PTRSIZE);
1802         case EEPPOINTER:
1803         case FPOINTER:
1804         case CPOINTER:
1805         case FUNCTION:
1806           return (FPTRSIZE);
1807         case GPOINTER:
1808           if (GPTRSIZE > FPTRSIZE)
1809             return (GPTRSIZE-1);
1810           else
1811             return (FPTRSIZE);
1812
1813         default:
1814           return (FPTRSIZE);
1815         }
1816     }
1817   return (FPTRSIZE);
1818 }
1819
1820 /*-----------------------------------------------------------------*/
1821 /* perform "usual unary conversions"                               */
1822 /*-----------------------------------------------------------------*/
1823 #if 0
1824 static operand *
1825 usualUnaryConversions (operand * op)
1826 {
1827   if (IS_INTEGRAL (operandType (op)))
1828     {
1829       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1830         {
1831           /* Widen to int. */
1832           return geniCodeCast (INTTYPE, op, TRUE);
1833         }
1834     }
1835   return op;
1836 }
1837 #endif
1838
1839 /*-----------------------------------------------------------------*/
1840 /* perform "usual binary conversions"                              */
1841 /*-----------------------------------------------------------------*/
1842
1843 static sym_link *
1844 usualBinaryConversions (operand ** op1, operand ** op2,
1845                         RESULT_TYPE resultType, int op)
1846 {
1847   sym_link *ctype;
1848   sym_link *rtype = operandType (*op2);
1849   sym_link *ltype = operandType (*op1);
1850
1851   ctype = computeType (ltype, rtype, resultType, op);
1852
1853   switch (op)
1854     {
1855       case '*':
1856       case '/':
1857       case '%':
1858         if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1859           {
1860             /* one byte operations: keep signedness for code generator */
1861             return ctype;
1862           }
1863         break;
1864       default:
1865         break;
1866     }
1867
1868   *op1 = geniCodeCast (ctype, *op1, TRUE);
1869   *op2 = geniCodeCast (ctype, *op2, TRUE);
1870
1871   return ctype;
1872 }
1873
1874 /*-----------------------------------------------------------------*/
1875 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1876 /*                          at address                             */
1877 /*-----------------------------------------------------------------*/
1878 operand *
1879 geniCodeRValue (operand * op, bool force)
1880 {
1881   iCode *ic;
1882   sym_link *type = operandType (op);
1883   sym_link *etype = getSpec (type);
1884
1885   /* if this is an array & already */
1886   /* an address then return this   */
1887   if (IS_AGGREGATE (type) ||
1888       (IS_PTR (type) && !force && !op->isaddr))
1889     return operandFromOperand (op);
1890
1891   /* if this is not an address then must be */
1892   /* rvalue already so return this one      */
1893   if (!op->isaddr)
1894     return op;
1895
1896   /* if this is not a temp symbol then */
1897   if (!IS_ITEMP (op) &&
1898       !force &&
1899       !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1900     {
1901       op = operandFromOperand (op);
1902       op->isaddr = 0;
1903       return op;
1904     }
1905
1906   if (IS_SPEC (type) &&
1907       IS_TRUE_SYMOP (op) &&
1908       (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1909       (options.model == MODEL_FLAT24) ))
1910     {
1911       op = operandFromOperand (op);
1912       op->isaddr = 0;
1913       return op;
1914     }
1915
1916   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1917   if (IS_PTR (type) && op->isaddr && force)
1918     type = type->next;
1919
1920   type = copyLinkChain (type);
1921
1922   IC_RESULT (ic) = newiTempOperand (type, 1);
1923   IC_RESULT (ic)->isaddr = 0;
1924
1925 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1926
1927   ADDTOCHAIN (ic);
1928
1929   return IC_RESULT (ic);
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* geniCodeCast - changes the value from one type to another       */
1934 /*-----------------------------------------------------------------*/
1935 static operand *
1936 geniCodeCast (sym_link * type, operand * op, bool implicit)
1937 {
1938   iCode *ic;
1939   sym_link *optype;
1940   sym_link *opetype = getSpec (optype = operandType (op));
1941   sym_link *restype;
1942   int errors=0;
1943
1944   /* one of them has size zero then error */
1945   if (IS_VOID (optype))
1946     {
1947       werror (E_CAST_ZERO);
1948       return op;
1949     }
1950
1951   if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1952     {
1953       geniCodeArray2Ptr (op);
1954       op->isaddr = 0;
1955     }
1956
1957   /* if the operand is already the desired type then do nothing */
1958   if (compareType (type, optype) == 1)
1959     return op;
1960
1961   /* if this is a literal then just change the type & return */
1962   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1963     {
1964       return operandFromValue (valCastLiteral (type,
1965                                                operandLitValue (op)));
1966     }
1967
1968   /* if casting to/from pointers, do some checking */
1969   if (IS_PTR(type)) { // to a pointer
1970     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1971       if (IS_INTEGRAL(optype)) {
1972         // maybe this is NULL, than it's ok.
1973         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1974           if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1975             // no way to set the storage
1976             if (IS_LITERAL(optype)) {
1977               werror(E_LITERAL_GENERIC);
1978               errors++;
1979             } else {
1980               werror(E_NONPTR2_GENPTR);
1981               errors++;
1982             }
1983           } else if (implicit) {
1984             werror(W_INTEGRAL2PTR_NOCAST);
1985             errors++;
1986           }
1987         }
1988       } else {
1989         // shouldn't do that with float, array or structure unless to void
1990         if (!IS_VOID(getSpec(type)) &&
1991             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1992           werror(E_INCOMPAT_TYPES);
1993           errors++;
1994         }
1995       }
1996     } else { // from a pointer to a pointer
1997       if (IS_GENPTR(type) && IS_VOID(type->next))
1998         { // cast to void* is always allowed
1999         }
2000       else if (IS_GENPTR(optype) && IS_VOID(optype->next))
2001         { // cast from void* is always allowed
2002         }
2003       else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
2004         // if not a pointer to a function
2005         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2006           if (implicit) { // if not to generic, they have to match
2007             if (!IS_GENPTR(type) &&
2008                 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
2009                   ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
2010                  )
2011                )
2012             {
2013               werror(E_INCOMPAT_PTYPES);
2014               errors++;
2015             }
2016           }
2017         }
2018       }
2019     }
2020   } else { // to a non pointer
2021     if (IS_PTR(optype)) { // from a pointer
2022       if (implicit) { // sneaky
2023         if (IS_INTEGRAL(type)) {
2024           werror(W_PTR2INTEGRAL_NOCAST);
2025           errors++;
2026         } else { // shouldn't do that with float, array or structure
2027           werror(E_INCOMPAT_TYPES);
2028           errors++;
2029         }
2030       }
2031     }
2032   }
2033   if (errors) {
2034     printFromToType (optype, type);
2035   }
2036
2037   /* if they are the same size create an assignment */
2038
2039   /* This seems very dangerous to me, since there are several */
2040   /* optimizations (for example, gcse) that don't notice the  */
2041   /* cast hidden in this assignement and may simplify an      */
2042   /* iCode to use the original (uncasted) operand.            */
2043   /* Unfortunately, other things break when this cast is      */
2044   /* made explicit. Need to fix this someday.                 */
2045   /* -- EEP, 2004/01/21                                       */
2046   if (getSize (type) == getSize (optype) &&
2047       !IS_BITFIELD (type) &&
2048       !IS_FLOAT (type) &&
2049       !IS_FLOAT (optype) &&
2050       !IS_FIXED (type) &&
2051       !IS_FIXED (optype) &&
2052       ((IS_SPEC (type) && IS_SPEC (optype)) ||
2053        (!IS_SPEC (type) && !IS_SPEC (optype))))
2054     {
2055       ic = newiCode ('=', NULL, op);
2056       IC_RESULT (ic) = newiTempOperand (type, 0);
2057       if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
2058           SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
2059       IC_RESULT (ic)->isaddr = 0;
2060     }
2061   else
2062     {
2063       ic = newiCode (CAST, operandFromLink (type),
2064                      geniCodeRValue (op, FALSE));
2065
2066       IC_RESULT (ic) = newiTempOperand (type, 0);
2067     }
2068
2069   /* preserve the storage class & output class */
2070   /* of the original variable                  */
2071   restype = getSpec (operandType (IC_RESULT (ic)));
2072   if (!IS_LITERAL(opetype) &&
2073       !IS_BIT(opetype))
2074     {
2075       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2076       SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2077     }
2078   ADDTOCHAIN (ic);
2079   return IC_RESULT (ic);
2080 }
2081
2082 /*-----------------------------------------------------------------*/
2083 /* geniCodeLabel - will create a Label                             */
2084 /*-----------------------------------------------------------------*/
2085 void
2086 geniCodeLabel (symbol * label)
2087 {
2088   iCode *ic;
2089
2090   ic = newiCodeLabelGoto (LABEL, label);
2091   ADDTOCHAIN (ic);
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* geniCodeGoto  - will create a Goto                              */
2096 /*-----------------------------------------------------------------*/
2097 void
2098 geniCodeGoto (symbol * label)
2099 {
2100   iCode *ic;
2101
2102   ic = newiCodeLabelGoto (GOTO, label);
2103   ADDTOCHAIN (ic);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* geniCodeMultiply - gen intermediate code for multiplication     */
2108 /*-----------------------------------------------------------------*/
2109 static operand *
2110 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2111 {
2112   iCode *ic;
2113   int p2 = 0;
2114   sym_link *resType;
2115   LRTYPE;
2116
2117   /* if they are both literal then we know the result */
2118   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2119     return operandFromValue (valMult (left->operand.valOperand,
2120                                       right->operand.valOperand));
2121
2122   if (IS_LITERAL(retype)) {
2123     p2 = powof2 ((TYPE_TARGET_ULONG) floatFromVal (right->operand.valOperand));
2124   }
2125
2126   resType = usualBinaryConversions (&left, &right, resultType, '*');
2127 #if 1
2128   rtype = operandType (right);
2129   retype = getSpec (rtype);
2130   ltype = operandType (left);
2131   letype = getSpec (ltype);
2132 #endif
2133
2134   /* if the right is a literal & power of 2 */
2135   /* then make it a left shift              */
2136   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2137      efficient in most cases than 2 bytes result = 2 bytes << literal
2138      if port has 1 byte muldiv */
2139   if ((p2 > 0) && !IS_FLOAT (letype) && !IS_FIXED (letype)
2140       && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2141            && (port->support.muldiv == 1))
2142       && strcmp (port->target, "pic16") != 0  /* don't shift for pic */
2143       && strcmp (port->target, "pic14") != 0)
2144     {
2145       if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2146         {
2147           /* LEFT_OP need same size for left and result, */
2148           left = geniCodeCast (resType, left, TRUE);
2149           ltype = operandType (left);
2150         }
2151       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2152     }
2153   else
2154     {
2155       /* if the size left or right > 1 then support routine */
2156       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2157         {
2158           if (IS_LITERAL (retype))
2159             ic = newiCode ('*', right, left); /* multiplication by support routine with one literal */
2160           else
2161             ic = newiCode ('*', left, right); /* multiplication by support routine */
2162           ic->supportRtn = 1;
2163         }
2164       else
2165         {
2166           ic = newiCode ('*', left, right);   /* normal multiplication */
2167         }
2168     }
2169   IC_RESULT (ic) = newiTempOperand (resType, 1);
2170
2171   ADDTOCHAIN (ic);
2172   return IC_RESULT (ic);
2173 }
2174
2175 /*-----------------------------------------------------------------*/
2176 /* geniCodeDivision - gen intermediate code for division           */
2177 /*-----------------------------------------------------------------*/
2178 static operand *
2179 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2180 {
2181   iCode *ic;
2182   int p2 = 0;
2183   sym_link *resType;
2184   sym_link *rtype = operandType (right);
2185   sym_link *retype = getSpec (rtype);
2186   sym_link *ltype = operandType (left);
2187   sym_link *letype = getSpec (ltype);
2188
2189   resType = usualBinaryConversions (&left, &right, resultType, '/');
2190
2191   /* if the right is a literal & power of 2
2192      and left is unsigned then make it a
2193      right shift */
2194   if (IS_LITERAL (retype) &&
2195       !IS_FLOAT (letype) &&
2196       !IS_FIXED (letype) &&
2197       IS_UNSIGNED(letype) &&
2198       ((p2 = powof2 ((TYPE_TARGET_ULONG)
2199                     floatFromVal (right->operand.valOperand))) > 0)) {
2200     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2201   }
2202   else
2203     {
2204       ic = newiCode ('/', left, right);         /* normal division */
2205       /* if the size left or right > 1 then support routine */
2206       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2207         ic->supportRtn = 1;
2208     }
2209   IC_RESULT (ic) = newiTempOperand (resType, 0);
2210
2211   ADDTOCHAIN (ic);
2212   return IC_RESULT (ic);
2213 }
2214 /*-----------------------------------------------------------------*/
2215 /* geniCodeModulus  - gen intermediate code for modulus            */
2216 /*-----------------------------------------------------------------*/
2217 static operand *
2218 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2219 {
2220   iCode *ic;
2221   sym_link *resType;
2222   LRTYPE;
2223
2224   /* if they are both literal then we know the result */
2225   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2226     return operandFromValue (valMod (left->operand.valOperand,
2227                                      right->operand.valOperand));
2228
2229   resType = usualBinaryConversions (&left, &right, resultType, '%');
2230
2231   /* now they are the same size */
2232   ic = newiCode ('%', left, right);
2233
2234   /* if the size left or right > 1 then support routine */
2235   if (getSize (ltype) > 1 || getSize (rtype) > 1)
2236     ic->supportRtn = 1;
2237   IC_RESULT (ic) = newiTempOperand (resType, 0);
2238
2239   ADDTOCHAIN (ic);
2240   return IC_RESULT (ic);
2241 }
2242
2243 /*-----------------------------------------------------------------*/
2244 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
2245 /*-----------------------------------------------------------------*/
2246 operand *
2247 geniCodePtrPtrSubtract (operand * left, operand * right)
2248 {
2249   iCode *ic;
2250   operand *result;
2251   LRTYPE;
2252
2253   /* if they are both literals then */
2254   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2255     {
2256       result = operandFromValue (valMinus (left->operand.valOperand,
2257                                            right->operand.valOperand));
2258       goto subtractExit;
2259     }
2260
2261   ic = newiCode ('-', left, right);
2262
2263   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2264   ADDTOCHAIN (ic);
2265
2266 subtractExit:
2267   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2268     return result;
2269   }
2270
2271   // should we really do this? is this ANSI?
2272   return geniCodeDivision (result,
2273                            operandFromLit (getSize (ltype->next)),
2274                            FALSE);
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* geniCodeSubtract - generates code for subtraction               */
2279 /*-----------------------------------------------------------------*/
2280 static operand *
2281 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2282 {
2283   iCode *ic;
2284   int isarray = 0;
2285   sym_link *resType;
2286   LRTYPE;
2287
2288   /* if they both pointers then */
2289   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2290       (IS_PTR (rtype) || IS_ARRAY (rtype)))
2291     return geniCodePtrPtrSubtract (left, right);
2292
2293   /* if they are both literal then we know the result */
2294   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2295       && left->isLiteral && right->isLiteral)
2296     return operandFromValue (valMinus (left->operand.valOperand,
2297                                        right->operand.valOperand));
2298
2299   /* if left is an array or pointer */
2300   if (IS_PTR (ltype) || IS_ARRAY (ltype))
2301     {
2302       isarray = left->isaddr;
2303       right = geniCodeMultiply (right,
2304                                 operandFromLit (getSize (ltype->next)),
2305                                 (getArraySizePtr(left) >= INTSIZE) ?
2306                                   RESULT_TYPE_INT :
2307                                   RESULT_TYPE_CHAR);
2308       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2309     }
2310   else
2311     {                           /* make them the same size */
2312       resType = usualBinaryConversions (&left, &right, resultType, '-');
2313     }
2314
2315   ic = newiCode ('-', left, right);
2316
2317   IC_RESULT (ic) = newiTempOperand (resType, 1);
2318   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2319
2320   /* if left or right is a float */
2321   if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2322       || IS_FIXED (ltype) || IS_FIXED (rtype))
2323     ic->supportRtn = 1;
2324
2325   ADDTOCHAIN (ic);
2326   return IC_RESULT (ic);
2327 }
2328
2329 /*-----------------------------------------------------------------*/
2330 /* geniCodeAdd - generates iCode for addition                      */
2331 /*-----------------------------------------------------------------*/
2332 static operand *
2333 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2334 {
2335   iCode *ic;
2336   sym_link *resType;
2337   operand *size;
2338   int isarray = 0;
2339   bool indexUnsigned;
2340   LRTYPE;
2341
2342   /* if the right side is LITERAL zero */
2343   /* return the left side              */
2344   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2345     return left;
2346
2347   /* if left is literal zero return right */
2348   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2349     return right;
2350
2351   /* if left is a pointer then size */
2352   if (IS_PTR (ltype) || IS_ARRAY(ltype))
2353     {
2354       isarray = left->isaddr;
2355       // there is no need to multiply with 1
2356       if (getSize (ltype->next) != 1)
2357         {
2358           size  = operandFromLit (getSize (ltype->next));
2359           SPEC_USIGN (getSpec (operandType (size))) = 1;
2360           indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2361           right = geniCodeMultiply (right, size, resultType);
2362           /* Even if right is a 'unsigned char',
2363              the result will be a 'signed int' due to the promotion rules.
2364              It doesn't make sense when accessing arrays, so let's fix it here: */
2365           if (indexUnsigned)
2366             SPEC_USIGN (getSpec (operandType (right))) = 1;
2367         }
2368       resType = copyLinkChain (ltype);
2369     }
2370   else
2371     { // make them the same size
2372       resType = usualBinaryConversions (&left, &right, resultType, '+');
2373     }
2374
2375   /* if they are both literals then we know */
2376   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2377       && left->isLiteral && right->isLiteral)
2378     return operandFromValue (valPlus (valFromType (ltype),
2379                                       valFromType (rtype)));
2380
2381   ic = newiCode ('+', left, right);
2382
2383   IC_RESULT (ic) = newiTempOperand (resType, 1);
2384   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2385
2386   /* if left or right is a float then support
2387      routine */
2388   if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
2389       || IS_FIXED (ltype) || IS_FIXED (rtype))
2390     ic->supportRtn = 1;
2391
2392   ADDTOCHAIN (ic);
2393
2394   return IC_RESULT (ic);
2395
2396 }
2397
2398 /*-----------------------------------------------------------------*/
2399 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate"  */
2400 /*-----------------------------------------------------------------*/
2401 sym_link *
2402 aggrToPtr (sym_link * type, bool force)
2403 {
2404   sym_link *etype;
2405   sym_link *ptype;
2406
2407   if (IS_PTR (type) && !force)
2408     return type;
2409
2410   etype = getSpec (type);
2411   ptype = newLink (DECLARATOR);
2412
2413   ptype->next = type;
2414
2415   /* set the pointer depending on the storage class */
2416   DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2417   return ptype;
2418 }
2419
2420 /*------------------------------------------------------------------*/
2421 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2422 /*------------------------------------------------------------------*/
2423 int
2424 aggrToPtrDclType (sym_link * type, bool force)
2425 {
2426   if (IS_PTR (type) && !force)
2427     return DCL_TYPE (type);
2428
2429   /* return the pointer depending on the storage class */
2430   return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* geniCodeArray2Ptr - array to pointer                            */
2435 /*-----------------------------------------------------------------*/
2436 static operand *
2437 geniCodeArray2Ptr (operand * op)
2438 {
2439   sym_link *optype = operandType (op);
2440   sym_link *opetype = getSpec (optype);
2441
2442   /* set the pointer depending on the storage class */
2443   DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2444
2445   op->isaddr = 0;
2446   return op;
2447 }
2448
2449
2450 /*-----------------------------------------------------------------*/
2451 /* geniCodeArray - array access                                    */
2452 /*-----------------------------------------------------------------*/
2453 static operand *
2454 geniCodeArray (operand * left, operand * right, int lvl)
2455 {
2456   iCode *ic;
2457   operand *size;
2458   sym_link *ltype = operandType (left);
2459   bool indexUnsigned;
2460   RESULT_TYPE resultType;
2461
2462   resultType = (getArraySizePtr(left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
2463   if (DCL_ELEM (ltype))
2464     {
2465       if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
2466         resultType = RESULT_TYPE_CHAR;
2467     }
2468
2469   if (IS_PTR (ltype))
2470     {
2471       if (IS_PTR (ltype->next) && left->isaddr)
2472         {
2473           left = geniCodeRValue (left, FALSE);
2474         }
2475
2476       return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl),
2477                                lvl);
2478     }
2479   size = operandFromLit (getSize (ltype->next));
2480   SPEC_USIGN (getSpec (operandType (size))) = 1;
2481   indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2482   right = geniCodeMultiply (right, size, resultType);
2483   /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2484      It doesn't make sense when accessing arrays, so let's fix it here: */
2485   if (indexUnsigned)
2486     SPEC_USIGN (getSpec (operandType (right))) = 1;
2487   /* we can check for limits here */
2488   /* already done in SDCCast.c
2489   if (isOperandLiteral (right) &&
2490       IS_ARRAY (ltype) &&
2491       DCL_ELEM (ltype) &&
2492       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2493     {
2494       werror (W_IDX_OUT_OF_BOUNDS,
2495               (int) operandLitValue (right) / getSize (ltype->next),
2496               DCL_ELEM (ltype));
2497     }
2498   */
2499
2500   ic = newiCode ('+', left, right);
2501
2502   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2503                                       !IS_AGGREGATE (ltype->next) &&
2504                                       !IS_PTR (ltype->next))
2505                                      ? ltype : ltype->next), 0);
2506
2507   if (!IS_AGGREGATE (ltype->next))
2508     {
2509       IC_RESULT (ic)->isaddr = 1;
2510       IC_RESULT (ic)->aggr2ptr = 1;
2511     }
2512   ADDTOCHAIN (ic);
2513
2514   return IC_RESULT (ic);
2515 }
2516
2517 /*-----------------------------------------------------------------*/
2518 /* geniCodeStruct - generates intermediate code for structures     */
2519 /*-----------------------------------------------------------------*/
2520 operand *
2521 geniCodeStruct (operand * left, operand * right, bool islval)
2522 {
2523   iCode *ic;
2524   sym_link *type = operandType (left);
2525   sym_link *etype = getSpec (type);
2526   sym_link *retype;
2527   symbol *element = getStructElement (SPEC_STRUCT (etype),
2528                                       right->operand.symOperand);
2529
2530   wassert(IS_SYMOP(right));
2531
2532   /* add the offset */
2533   ic = newiCode ('+', left, operandFromLit (element->offset));
2534
2535   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2536
2537   /* preserve the storage & output class of the struct */
2538   /* as well as the volatile attribute */
2539   retype = getSpec (operandType (IC_RESULT (ic)));
2540   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2541   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2542   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2543   SPEC_CONST (retype) |= SPEC_CONST (etype);
2544
2545   if (IS_PTR (element->type))
2546     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2547
2548   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2549
2550   ADDTOCHAIN (ic);
2551   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* geniCodePostInc - generate int code for Post increment          */
2556 /*-----------------------------------------------------------------*/
2557 operand *
2558 geniCodePostInc (operand * op)
2559 {
2560   iCode *ic;
2561   operand *rOp;
2562   sym_link *optype = operandType (op);
2563   operand *result;
2564   operand *rv = (IS_ITEMP (op) ?
2565                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2566                  op);
2567   sym_link *rvtype = operandType (rv);
2568   int size = 0;
2569
2570   /* if this is not an address we have trouble */
2571   if (!op->isaddr)
2572     {
2573       werror (E_LVALUE_REQUIRED, "++");
2574       return op;
2575     }
2576
2577   rOp = newiTempOperand (rvtype, 0);
2578   OP_SYMBOL(rOp)->noSpilLoc = 1;
2579
2580   if (IS_ITEMP (rv))
2581     OP_SYMBOL(rv)->noSpilLoc = 1;
2582
2583   geniCodeAssign (rOp, rv, 0, 0);
2584
2585   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2586   if (size == 0)
2587     werror(W_SIZEOF_VOID);
2588   if (IS_FLOAT (rvtype))
2589     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2590   else if (IS_FIXED16X16 (rvtype))
2591     ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
2592   else
2593     ic = newiCode ('+', rv, operandFromLit (size));
2594
2595   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2596   ADDTOCHAIN (ic);
2597
2598   geniCodeAssign (op, result, 0, 0);
2599
2600   return rOp;
2601
2602 }
2603
2604 /*-----------------------------------------------------------------*/
2605 /* geniCodePreInc - generate code for preIncrement                 */
2606 /*-----------------------------------------------------------------*/
2607 operand *
2608 geniCodePreInc (operand * op, bool lvalue)
2609 {
2610   iCode *ic;
2611   sym_link *optype = operandType (op);
2612   operand *rop = (IS_ITEMP (op) ?
2613                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2614                   op);
2615   sym_link *roptype = operandType (rop);
2616   operand *result;
2617   int size = 0;
2618
2619   if (!op->isaddr)
2620     {
2621       werror (E_LVALUE_REQUIRED, "++");
2622       return op;
2623     }
2624
2625   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2626   if (size == 0)
2627     werror(W_SIZEOF_VOID);
2628   if (IS_FLOAT (roptype))
2629     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2630   else if (IS_FIXED16X16 (roptype))
2631     ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
2632   else
2633     ic = newiCode ('+', rop, operandFromLit (size));
2634   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2635   ADDTOCHAIN (ic);
2636
2637   (void) geniCodeAssign (op, result, 0, 0);
2638   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2639     return op;
2640   else
2641     return result;
2642 }
2643
2644 /*-----------------------------------------------------------------*/
2645 /* geniCodePostDec - generates code for Post decrement             */
2646 /*-----------------------------------------------------------------*/
2647 operand *
2648 geniCodePostDec (operand * op)
2649 {
2650   iCode *ic;
2651   operand *rOp;
2652   sym_link *optype = operandType (op);
2653   operand *result;
2654   operand *rv = (IS_ITEMP (op) ?
2655                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2656                  op);
2657   sym_link *rvtype = operandType (rv);
2658   int size = 0;
2659
2660   /* if this is not an address we have trouble */
2661   if (!op->isaddr)
2662     {
2663       werror (E_LVALUE_REQUIRED, "--");
2664       return op;
2665     }
2666
2667   rOp = newiTempOperand (rvtype, 0);
2668   OP_SYMBOL(rOp)->noSpilLoc = 1;
2669
2670   if (IS_ITEMP (rv))
2671     OP_SYMBOL(rv)->noSpilLoc = 1;
2672
2673   geniCodeAssign (rOp, rv, 0, 0);
2674
2675   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2676   if (size == 0)
2677     werror(W_SIZEOF_VOID);
2678   if (IS_FLOAT (rvtype))
2679     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2680   else if (IS_FIXED16X16 (rvtype))
2681     ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
2682   else
2683     ic = newiCode ('-', rv, operandFromLit (size));
2684
2685   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2686   ADDTOCHAIN (ic);
2687
2688   geniCodeAssign (op, result, 0, 0);
2689
2690   return rOp;
2691
2692 }
2693
2694 /*-----------------------------------------------------------------*/
2695 /* geniCodePreDec - generate code for pre  decrement               */
2696 /*-----------------------------------------------------------------*/
2697 operand *
2698 geniCodePreDec (operand * op, bool lvalue)
2699 {
2700   iCode *ic;
2701   sym_link *optype = operandType (op);
2702   operand *rop = (IS_ITEMP (op) ?
2703                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2704                   op);
2705   sym_link *roptype = operandType (rop);
2706   operand *result;
2707   int size = 0;
2708
2709   if (!op->isaddr)
2710     {
2711       werror (E_LVALUE_REQUIRED, "--");
2712       return op;
2713     }
2714
2715   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2716   if (size == 0)
2717     werror(W_SIZEOF_VOID);
2718   if (IS_FLOAT (roptype))
2719     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2720   else if (IS_FIXED16X16 (roptype))
2721     ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
2722   else
2723     ic = newiCode ('-', rop, operandFromLit (size));
2724   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2725   ADDTOCHAIN (ic);
2726
2727   (void) geniCodeAssign (op, result, 0, 0);
2728   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2729     return op;
2730   else
2731     return result;
2732 }
2733
2734
2735 /*-----------------------------------------------------------------*/
2736 /* geniCodeBitwise - gen int code for bitWise  operators           */
2737 /*-----------------------------------------------------------------*/
2738 operand *
2739 geniCodeBitwise (operand * left, operand * right,
2740                  int oper, sym_link * resType)
2741 {
2742   iCode *ic;
2743
2744   left = geniCodeCast (resType, left, TRUE);
2745   right = geniCodeCast (resType, right, TRUE);
2746
2747   ic = newiCode (oper, left, right);
2748   IC_RESULT (ic) = newiTempOperand (resType, 0);
2749
2750   ADDTOCHAIN (ic);
2751   return IC_RESULT (ic);
2752 }
2753
2754 /*-----------------------------------------------------------------*/
2755 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2756 /*-----------------------------------------------------------------*/
2757 operand *
2758 geniCodeAddressOf (operand * op)
2759 {
2760   iCode *ic;
2761   sym_link *p;
2762   sym_link *optype = operandType (op);
2763   sym_link *opetype = getSpec (optype);
2764
2765   if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2766     {
2767       op = operandFromOperand (op);
2768       op->isaddr = 0;
2769       return op;
2770     }
2771
2772   /* lvalue check already done in decorateType */
2773   /* this must be a lvalue */
2774 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2775 /*  werror (E_LVALUE_REQUIRED,"&"); */
2776 /*  return op; */
2777 /*     } */
2778
2779   p = newLink (DECLARATOR);
2780
2781   /* set the pointer depending on the storage class */
2782   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2783
2784   p->next = copyLinkChain (optype);
2785
2786   /* if already a temp */
2787   if (IS_ITEMP (op))
2788     {
2789       setOperandType (op, p);
2790       op->isaddr = 0;
2791       return op;
2792     }
2793
2794   /* otherwise make this of the type coming in */
2795   ic = newiCode (ADDRESS_OF, op, NULL);
2796   IC_RESULT (ic) = newiTempOperand (p, 1);
2797   IC_RESULT (ic)->isaddr = 0;
2798   ADDTOCHAIN (ic);
2799   return IC_RESULT (ic);
2800 }
2801
2802 /*-----------------------------------------------------------------*/
2803 /* setOClass - sets the output class depending on the pointer type */
2804 /*-----------------------------------------------------------------*/
2805 void
2806 setOClass (sym_link * ptr, sym_link * spec)
2807 {
2808   switch (DCL_TYPE (ptr))
2809     {
2810     case POINTER:
2811       SPEC_OCLS (spec) = data;
2812       break;
2813
2814     case GPOINTER:
2815       SPEC_OCLS (spec) = generic;
2816       break;
2817
2818     case FPOINTER:
2819       SPEC_OCLS (spec) = xdata;
2820       break;
2821
2822     case CPOINTER:
2823       SPEC_OCLS (spec) = code;
2824       break;
2825
2826     case IPOINTER:
2827       SPEC_OCLS (spec) = idata;
2828       break;
2829
2830     case PPOINTER:
2831       SPEC_OCLS (spec) = xstack;
2832       break;
2833
2834     case EEPPOINTER:
2835       SPEC_OCLS (spec) = eeprom;
2836       break;
2837
2838     default:
2839       break;
2840
2841     }
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2846 /*-----------------------------------------------------------------*/
2847 operand *
2848 geniCodeDerefPtr (operand * op,int lvl)
2849 {
2850   sym_link *rtype, *retype;
2851   sym_link *optype = operandType (op);
2852
2853   // if this is an array then array access
2854   if (IS_ARRAY (optype)) {
2855     // don't worry, this will be optimized out later
2856     return geniCodeArray (op, operandFromLit (0), lvl);
2857   }
2858
2859   // just in case someone screws up
2860   wassert (IS_PTR (optype));
2861
2862   if (IS_TRUE_SYMOP (op))
2863     {
2864       op->isaddr = 1;
2865       op = geniCodeRValue (op, TRUE);
2866     }
2867
2868   /* now get rid of the pointer part */
2869   if (isLvaluereq(lvl) && IS_ITEMP (op))
2870     {
2871       retype = getSpec (rtype = copyLinkChain (optype));
2872     }
2873   else
2874     {
2875       retype = getSpec (rtype = copyLinkChain (optype->next));
2876       /* outputclass needs 2b updated */
2877       setOClass (optype, retype);
2878     }
2879
2880   op->isGptr = IS_GENPTR (optype);
2881
2882   op->isaddr = (IS_PTR (rtype) ||
2883                 IS_STRUCT (rtype) ||
2884                 IS_INT (rtype) ||
2885                 IS_CHAR (rtype) ||
2886                 IS_FLOAT (rtype) ||
2887                 IS_FIXED (rtype));
2888
2889   if (!isLvaluereq(lvl))
2890     op = geniCodeRValue (op, TRUE);
2891
2892   setOperandType (op, rtype);
2893
2894   return op;
2895 }
2896
2897 /*-----------------------------------------------------------------*/
2898 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2899 /*-----------------------------------------------------------------*/
2900 operand *
2901 geniCodeUnaryMinus (operand * op)
2902 {
2903   iCode *ic;
2904   sym_link *optype = operandType (op);
2905
2906   if (IS_LITERAL (optype))
2907     return operandFromLit (-floatFromVal (op->operand.valOperand));
2908
2909   ic = newiCode (UNARYMINUS, op, NULL);
2910   IC_RESULT (ic) = newiTempOperand (optype, 0);
2911   ADDTOCHAIN (ic);
2912   return IC_RESULT (ic);
2913 }
2914
2915 /*-----------------------------------------------------------------*/
2916 /* geniCodeLeftShift - gen i code for left shift                   */
2917 /*-----------------------------------------------------------------*/
2918 operand *
2919 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2920 {
2921   iCode *ic;
2922   sym_link *resType;
2923
2924   ic = newiCode (LEFT_OP, left, right);
2925
2926   resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2927   IC_RESULT (ic) = newiTempOperand (resType, 0);
2928   ADDTOCHAIN (ic);
2929   return IC_RESULT (ic);
2930 }
2931
2932 /*-----------------------------------------------------------------*/
2933 /* geniCodeRightShift - gen i code for right shift                 */
2934 /*-----------------------------------------------------------------*/
2935 operand *
2936 geniCodeRightShift (operand * left, operand * right)
2937 {
2938   iCode *ic;
2939
2940   ic = newiCode (RIGHT_OP, left, right);
2941   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2942   ADDTOCHAIN (ic);
2943   return IC_RESULT (ic);
2944 }
2945
2946 /*-----------------------------------------------------------------*/
2947 /* geniCodeLogic- logic code                                       */
2948 /*-----------------------------------------------------------------*/
2949 static operand *
2950 geniCodeLogic (operand * left, operand * right, int op)
2951 {
2952   iCode *ic;
2953   sym_link *ctype;
2954   sym_link *rtype = operandType (right);
2955   sym_link *ltype = operandType (left);
2956
2957   /* left is integral type and right is literal then
2958      check if the literal value is within bounds */
2959   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2960     {
2961       CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
2962       switch (ccr_result)
2963         {
2964           case CCR_ALWAYS_TRUE:
2965           case CCR_ALWAYS_FALSE:
2966             if (!options.lessPedantic)
2967               werror (W_COMP_RANGE, "true resp. false");
2968             return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
2969           default:
2970             break;
2971         }
2972     }
2973
2974   /* if one operand is a pointer and the other is a literal generic void pointer,
2975      change the type of the literal generic void pointer to match the other pointer */
2976   if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2977       && IS_PTR (rtype) && !IS_GENPTR(rtype))
2978     {
2979       /* find left's definition */
2980       ic = (iCode *) setFirstItem (iCodeChain);
2981       while (ic)
2982         {
2983           if (((ic->op == CAST) || (ic->op == '='))
2984               && isOperandEqual(left, IC_RESULT (ic)))
2985             break;
2986           else
2987             ic = setNextItem (iCodeChain);
2988         }
2989       /* if casting literal to generic pointer, then cast to rtype instead */
2990       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
2991         {
2992           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2993           ltype = operandType(left);
2994         }
2995     }
2996   if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2997       && IS_PTR (ltype) && !IS_GENPTR(ltype))
2998     {
2999       /* find right's definition */
3000       ic = (iCode *) setFirstItem (iCodeChain);
3001       while (ic)
3002         {
3003           if (((ic->op == CAST) || (ic->op == '='))
3004               && isOperandEqual(right, IC_RESULT (ic)))
3005             break;
3006           else
3007             ic = setNextItem (iCodeChain);
3008         }
3009       /* if casting literal to generic pointer, then cast to rtype instead */
3010       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
3011         {
3012           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
3013           rtype = operandType(right);
3014         }
3015     }
3016
3017   ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_BIT, 0);
3018
3019   ic = newiCode (op, left, right);
3020   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
3021
3022   /* if comparing float
3023      and not a '==' || '!=' || '&&' || '||' (these
3024      will be inlined */
3025   if (IS_FLOAT(ctype) &&
3026       op != EQ_OP &&
3027       op != NE_OP &&
3028       op != AND_OP &&
3029       op != OR_OP)
3030    ic->supportRtn = 1;
3031
3032   /* if comparing a fixed type use support functions */
3033   if (IS_FIXED(ctype))
3034     ic->supportRtn = 1;
3035
3036   ADDTOCHAIN (ic);
3037   return IC_RESULT (ic);
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /* geniCodeLogicAndOr - && || operations                           */
3042 /*-----------------------------------------------------------------*/
3043 static operand *
3044 geniCodeLogicAndOr (ast *tree, int lvl)
3045 {
3046   iCode *ic;
3047   sym_link *type;
3048   symbol *falseLabel = newiTempLabel (NULL);
3049   symbol *trueLabel  = newiTempLabel (NULL);
3050   symbol *exitLabel  = newiTempLabel (NULL);
3051   operand *op, *result, *condition;
3052
3053   /* AND_OP and OR_OP are no longer generated because of bug-905492.
3054      They can be reenabled by executing the following block. If you find
3055      a decent optimization you could start right here:
3056   */
3057 #if 0
3058   if (0)
3059     {
3060        operand *leftOp, *rightOp;
3061
3062        leftOp  = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3063        rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3064
3065        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3066     }
3067 #endif
3068
3069   /* generate two IFX for the '&&' or '||' op */
3070
3071   /* evaluate left operand */
3072   condition = ast2iCode (tree->left, lvl + 1);
3073   op = geniCodeRValue (condition, FALSE);
3074
3075   /* test left operand */
3076   if (tree->opval.op == AND_OP)
3077     ic = newiCodeCondition (op, NULL, falseLabel);
3078   else /* OR_OP */
3079     ic = newiCodeCondition (op, trueLabel, NULL);
3080   ADDTOCHAIN (ic);
3081
3082   /* evaluate right operand */
3083   condition = ast2iCode (tree->right, lvl + 1);
3084   op = geniCodeRValue (condition, FALSE);
3085
3086   /* test right operand */
3087   ic = newiCodeCondition (op, trueLabel, NULL);
3088   ADDTOCHAIN (ic);
3089
3090   /* store 0 or 1 in result */
3091   type = (SPEC_NOUN(tree->ftype) == V_BIT) ? newBoolLink() : newCharLink();
3092   result = newiTempOperand (type, 1);
3093
3094   geniCodeLabel (falseLabel);
3095   geniCodeAssign (result, operandFromLit (0), 0, 0);
3096   /* generate an unconditional goto */
3097   geniCodeGoto (exitLabel);
3098
3099   geniCodeLabel (trueLabel);
3100   geniCodeAssign (result, operandFromLit (1), 0, 0);
3101
3102   geniCodeLabel (exitLabel);
3103
3104   return result;
3105 }
3106
3107 /*-----------------------------------------------------------------*/
3108 /* geniCodeUnary - for a generic unary operation                   */
3109 /*-----------------------------------------------------------------*/
3110 operand *
3111 geniCodeUnary (operand * op, int oper)
3112 {
3113   iCode *ic = newiCode (oper, op, NULL);
3114
3115   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3116   ADDTOCHAIN (ic);
3117   return IC_RESULT (ic);
3118 }
3119
3120 /*-----------------------------------------------------------------*/
3121 /* geniCodeBinary - for a generic binary operation                 */
3122 /*-----------------------------------------------------------------*/
3123 operand *
3124 geniCodeBinary (operand * left, operand * right, int oper)
3125 {
3126   iCode *ic = newiCode (oper, left, right);
3127
3128   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
3129   ADDTOCHAIN (ic);
3130   return IC_RESULT (ic);
3131 }
3132
3133 /*-----------------------------------------------------------------*/
3134 /* geniCodeConditional - geniCode for '?' ':' operation            */
3135 /*-----------------------------------------------------------------*/
3136 operand *
3137 geniCodeConditional (ast * tree,int lvl)
3138 {
3139   iCode *ic;
3140   symbol *falseLabel = newiTempLabel (NULL);
3141   symbol *exitLabel = newiTempLabel (NULL);
3142   operand *cond = ast2iCode (tree->left,lvl+1);
3143   operand *true, *false, *result;
3144
3145   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3146                           NULL, falseLabel);
3147   ADDTOCHAIN (ic);
3148
3149   true = ast2iCode (tree->right->left,lvl+1);
3150
3151   /* move the value to a new Operand */
3152   result = newiTempOperand (tree->right->ftype, 0);
3153   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3154
3155   /* generate an unconditional goto */
3156   geniCodeGoto (exitLabel);
3157
3158   /* now for the right side */
3159   geniCodeLabel (falseLabel);
3160
3161   false = ast2iCode (tree->right->right,lvl+1);
3162   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3163
3164   /* create the exit label */
3165   geniCodeLabel (exitLabel);
3166
3167   return result;
3168 }
3169
3170 /*-----------------------------------------------------------------*/
3171 /* geniCodeAssign - generate code for assignment                   */
3172 /*-----------------------------------------------------------------*/
3173 operand *
3174 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3175 {
3176   iCode *ic;
3177   sym_link *ltype = operandType (left);
3178   sym_link *rtype = operandType (right);
3179
3180   if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3181     {
3182       werror (E_LVALUE_REQUIRED, "assignment");
3183       return left;
3184     }
3185
3186   /* left is integral type and right is literal then
3187      check if the literal value is within bounds */
3188   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
3189       checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL &&
3190       !options.lessPedantic)
3191     {
3192       werror (W_LIT_OVERFLOW);
3193     }
3194
3195   /* if the left & right type don't exactly match */
3196   /* if pointer set then make sure the check is
3197      done with the type & not the pointer */
3198   /* then cast rights type to left */
3199
3200   /* first check the type for pointer assignement */
3201   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3202       compareType (ltype, rtype) <= 0)
3203     {
3204       if (compareType (ltype->next, rtype) < 0)
3205         right = geniCodeCast (ltype->next, right, TRUE);
3206     }
3207   else if (compareType (ltype, rtype) < 0)
3208     right = geniCodeCast (ltype, right, TRUE);
3209
3210   /* If left is a true symbol & ! volatile
3211      create an assignment to temporary for
3212      the right & then assign this temporary
3213      to the symbol. This is SSA (static single
3214      assignment). Isn't it simple and folks have
3215      published mountains of paper on it */
3216   if (IS_TRUE_SYMOP (left) &&
3217       !isOperandVolatile (left, FALSE) &&
3218       isOperandGlobal (left))
3219     {
3220       symbol *sym = NULL;
3221       operand *newRight;
3222
3223       if (IS_TRUE_SYMOP (right))
3224         sym = OP_SYMBOL (right);
3225       ic = newiCode ('=', NULL, right);
3226       IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
3227       /* avoid double fetch from volatile right, see bug 1369874 */
3228       if (!isOperandVolatile (right, FALSE))
3229         SPIL_LOC (newRight) = sym;
3230       right = newRight;
3231       ADDTOCHAIN (ic);
3232     }
3233
3234   ic = newiCode ('=', NULL, right);
3235   IC_RESULT (ic) = left;
3236   ADDTOCHAIN (ic);
3237
3238   /* if left isgptr flag is set then support
3239      routine will be required */
3240   if (left->isGptr)
3241     ic->supportRtn = 1;
3242
3243   ic->nosupdate = nosupdate;
3244   /* left could be a pointer assignment,
3245      return the properly casted right instead */
3246   return right;
3247 }
3248
3249 /*-----------------------------------------------------------------*/
3250 /* geniCodeDummyRead - generate code for dummy read                */
3251 /*-----------------------------------------------------------------*/
3252 static void
3253 geniCodeDummyRead (operand * op)
3254 {
3255   iCode *ic;
3256   sym_link *type = operandType (op);
3257
3258   if (!IS_VOLATILE(type))
3259     return;
3260
3261   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3262   ADDTOCHAIN (ic);
3263
3264   ic->nosupdate = 1;
3265 }
3266
3267 /*-----------------------------------------------------------------*/
3268 /* geniCodeSEParms - generate code for side effecting fcalls       */
3269 /*-----------------------------------------------------------------*/
3270 static void
3271 geniCodeSEParms (ast * parms,int lvl)
3272 {
3273   if (!parms)
3274     return;
3275
3276   if (parms->type == EX_OP && parms->opval.op == PARAM)
3277     {
3278       geniCodeSEParms (parms->left,lvl);
3279       geniCodeSEParms (parms->right,lvl);
3280       return;
3281     }
3282
3283   /* hack don't like this but too lazy to think of
3284      something better */
3285   if (IS_ADDRESS_OF_OP (parms))
3286     parms->left->lvalue = 1;
3287
3288   if (IS_CAST_OP (parms) &&
3289       IS_PTR (parms->ftype) &&
3290       IS_ADDRESS_OF_OP (parms->right))
3291     parms->right->left->lvalue = 1;
3292
3293   parms->opval.oprnd =
3294     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3295
3296   parms->type = EX_OPERAND;
3297   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3298                 SPEC_ARGREG(parms->ftype);
3299 }
3300
3301 /*-----------------------------------------------------------------*/
3302 /* geniCodeParms - generates parameters                            */
3303 /*-----------------------------------------------------------------*/
3304 value *
3305 geniCodeParms (ast * parms, value *argVals, int *stack,
3306                sym_link * ftype, int lvl)
3307 {
3308   iCode *ic;
3309   operand *pval;
3310
3311   if (!parms)
3312     return argVals;
3313
3314   if (argVals==NULL) {
3315     // first argument
3316     argVals = FUNC_ARGS (ftype);
3317   }
3318
3319   /* if this is a param node then do the left & right */
3320   if (parms->type == EX_OP && parms->opval.op == PARAM)
3321     {
3322       argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3323       argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3324       return argVals;
3325     }
3326
3327   /* get the parameter value */
3328   if (parms->type == EX_OPERAND)
3329     pval = parms->opval.oprnd;
3330   else
3331     {
3332       /* maybe this else should go away ?? */
3333       /* hack don't like this but too lazy to think of
3334          something better */
3335       if (IS_ADDRESS_OF_OP (parms))
3336         parms->left->lvalue = 1;
3337
3338       if (IS_CAST_OP (parms) &&
3339           IS_PTR (parms->ftype) &&
3340           IS_ADDRESS_OF_OP (parms->right))
3341         parms->right->left->lvalue = 1;
3342
3343       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3344     }
3345
3346   /* if register parm then make it a send */
3347   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3348       IFFUNC_ISBUILTIN(ftype))
3349     {
3350       ic = newiCode (SEND, pval, NULL);
3351       ic->argreg = SPEC_ARGREG(parms->etype);
3352       ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3353       ADDTOCHAIN (ic);
3354     }
3355   else
3356     {
3357       /* now decide whether to push or assign */
3358       if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3359         {
3360
3361           /* assign */
3362           operand *top = operandFromSymbol (argVals->sym);
3363           /* clear useDef and other bitVectors */
3364           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3365           geniCodeAssign (top, pval, 1, 0);
3366         }
3367       else
3368         {
3369           sym_link *p = operandType (pval);
3370           /* push */
3371           ic = newiCode (IPUSH, pval, NULL);
3372           ic->parmPush = 1;
3373           /* update the stack adjustment */
3374           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3375           ADDTOCHAIN (ic);
3376         }
3377     }
3378
3379   argVals=argVals->next;
3380   return argVals;
3381 }
3382
3383 /*-----------------------------------------------------------------*/
3384 /* geniCodeCall - generates temp code for calling                  */
3385 /*-----------------------------------------------------------------*/
3386 operand *
3387 geniCodeCall (operand * left, ast * parms,int lvl)
3388 {
3389   iCode *ic;
3390   operand *result;
3391   sym_link *type, *etype;
3392   sym_link *ftype;
3393   int stack = 0;
3394
3395   if (!IS_FUNC(OP_SYMBOL(left)->type) &&
3396       !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
3397     werror (E_FUNCTION_EXPECTED);
3398     return operandFromValue(valueFromLit(0));
3399   }
3400
3401   /* take care of parameters with side-effecting
3402      function calls in them, this is required to take care
3403      of overlaying function parameters */
3404   geniCodeSEParms (parms,lvl);
3405
3406   ftype = operandType (left);
3407   if (IS_FUNCPTR (ftype))
3408     ftype = ftype->next;
3409
3410   /* first the parameters */
3411   geniCodeParms (parms, NULL, &stack, ftype, lvl);
3412
3413   /* now call : if symbol then pcall */
3414   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3415     ic = newiCode (PCALL, left, NULL);
3416   } else {
3417     ic = newiCode (CALL, left, NULL);
3418   }
3419
3420   type = copyLinkChain (ftype->next);
3421   etype = getSpec (type);
3422   SPEC_EXTR (etype) = 0;
3423   IC_RESULT (ic) = result = newiTempOperand (type, 1);
3424
3425   ADDTOCHAIN (ic);
3426
3427   /* stack adjustment after call */
3428   ic->parmBytes = stack;
3429
3430   return result;
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* geniCodeReceive - generate intermediate code for "receive"      */
3435 /*-----------------------------------------------------------------*/
3436 static void
3437 geniCodeReceive (value * args, operand * func)
3438 {
3439   unsigned char paramByteCounter = 0;
3440
3441   /* for all arguments that are passed in registers */
3442   while (args)
3443     {
3444       if (IS_REGPARM (args->etype))
3445         {
3446           operand *opr = operandFromValue (args);
3447           operand *opl;
3448           symbol *sym = OP_SYMBOL (opr);
3449           iCode *ic;
3450
3451           /* we will use it after all optimizations
3452              and before liveRange calculation */
3453           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3454             {
3455
3456               if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3457                   options.stackAuto == 0 &&
3458                   (!(options.model == MODEL_FLAT24)) )
3459                 {
3460                 }
3461               else
3462                 {
3463                   opl = newiTempOperand (args->type, 0);
3464                   sym->reqv = opl;
3465                   sym->reqv->key = sym->key;
3466                   OP_SYMBOL (sym->reqv)->key = sym->key;
3467                   OP_SYMBOL (sym->reqv)->isreqv = 1;
3468                   OP_SYMBOL (sym->reqv)->islocal = 0;
3469                   SPIL_LOC (sym->reqv) = sym;
3470                 }
3471             }
3472
3473           ic = newiCode (RECEIVE, func, NULL);
3474           ic->argreg = SPEC_ARGREG(args->etype);
3475           if (ic->argreg == 1) {
3476               currFunc->recvSize = getSize (sym->type);
3477           }
3478           IC_RESULT (ic) = opr;
3479
3480           /* misuse of parmBytes (normally used for functions)
3481            * to save estimated stack position of this argument.
3482            * Normally this should be zero for RECEIVE iCodes.
3483            * No idea if this causes side effects on other ports. - dw
3484            */
3485           ic->parmBytes = paramByteCounter;
3486
3487           /* what stack position do we have? */
3488           paramByteCounter += getSize (sym->type);
3489
3490           ADDTOCHAIN (ic);
3491         }
3492
3493       args = args->next;
3494     }
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* geniCodeFunctionBody - create the function body                 */
3499 /*-----------------------------------------------------------------*/
3500 void
3501 geniCodeFunctionBody (ast * tree,int lvl)
3502 {
3503   iCode *ic;
3504   operand *func;
3505   sym_link *fetype;
3506   int savelineno;
3507
3508   /* reset the auto generation */
3509   /* numbers */
3510   iTempNum = 0;
3511   iTempLblNum = 0;
3512   operandKey = 0;
3513   iCodeKey = 0;
3514   func = ast2iCode (tree->left,lvl+1);
3515   fetype = getSpec (operandType (func));
3516
3517   savelineno = lineno;
3518   lineno = OP_SYMBOL (func)->lineDef;
3519   /* create an entry label */
3520   geniCodeLabel (entryLabel);
3521   lineno = savelineno;
3522
3523   /* create a proc icode */
3524   ic = newiCode (FUNCTION, func, NULL);
3525   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3526   ic->tree = tree;
3527
3528   ADDTOCHAIN (ic);
3529
3530   /* for all parameters that are passed
3531      on registers add a "receive" */
3532   geniCodeReceive (tree->values.args, func);
3533
3534   /* generate code for the body */
3535   ast2iCode (tree->right,lvl+1);
3536
3537   /* create a label for return */
3538   geniCodeLabel (returnLabel);
3539
3540   /* now generate the end proc */
3541   ic = newiCode (ENDFUNCTION, func, NULL);
3542   ic->tree = tree;
3543   ADDTOCHAIN (ic);
3544   return;
3545 }
3546
3547 /*-----------------------------------------------------------------*/
3548 /* geniCodeReturn - gen icode for 'return' statement               */
3549 /*-----------------------------------------------------------------*/
3550 void
3551 geniCodeReturn (operand * op)
3552 {
3553   iCode *ic;
3554
3555   /* if the operand is present force an rvalue */
3556   if (op)
3557     op = geniCodeRValue (op, FALSE);
3558
3559   ic = newiCode (RETURN, op, NULL);
3560   ADDTOCHAIN (ic);
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* geniCodeIfx - generates code for extended if statement          */
3565 /*-----------------------------------------------------------------*/
3566 void
3567 geniCodeIfx (ast * tree,int lvl)
3568 {
3569   iCode *ic;
3570   operand *condition = ast2iCode (tree->left,lvl+1);
3571   sym_link *cetype;
3572
3573   /* if condition is null then exit */
3574   if (!condition)
3575     goto exit;
3576   else
3577     condition = geniCodeRValue (condition, FALSE);
3578
3579   cetype = getSpec (operandType (condition));
3580   /* if the condition is a literal */
3581   if (IS_LITERAL (cetype))
3582     {
3583       if (floatFromVal (condition->operand.valOperand))
3584         {
3585           if (tree->trueLabel)
3586             geniCodeGoto (tree->trueLabel);
3587           else
3588             assert (0);
3589         }
3590       else
3591         {
3592           if (tree->falseLabel)
3593             geniCodeGoto (tree->falseLabel);
3594         }
3595       goto exit;
3596     }
3597
3598   if (tree->trueLabel)
3599     {
3600       ic = newiCodeCondition (condition,
3601                               tree->trueLabel,
3602                               NULL);
3603       ADDTOCHAIN (ic);
3604
3605       if (tree->falseLabel)
3606         geniCodeGoto (tree->falseLabel);
3607     }
3608   else
3609     {
3610       ic = newiCodeCondition (condition,
3611                               NULL,
3612                               tree->falseLabel);
3613       ADDTOCHAIN (ic);
3614     }
3615
3616 exit:
3617   ast2iCode (tree->right,lvl+1);
3618 }
3619
3620 /*-----------------------------------------------------------------*/
3621 /* geniCodeJumpTable - tries to create a jump table for switch     */
3622 /*-----------------------------------------------------------------*/
3623 int
3624 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3625 {
3626   int min, max, cnt = 1;
3627   int i, t;
3628   value *vch;
3629   iCode *ic;
3630   operand *boundary;
3631   symbol *falseLabel;
3632   set *labels = NULL;
3633   int needRangeCheck = !optimize.noJTabBoundary
3634                        || tree->values.switchVals.swDefault;
3635   sym_link *cetype = getSpec (operandType (cond));
3636   int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3637   int sizeofMatchJump, sizeofJumpTable;
3638   int sizeIndex;
3639
3640   if (!tree || !caseVals)
3641     return 0;
3642
3643   /* the criteria for creating a jump table is */
3644   /* all integer numbers between the maximum & minimum must */
3645   /* be present , the maximum value should not exceed 255 */
3646   /* If not all integer numbers are present the algorithm */
3647   /* inserts jumps to the default label for the missing numbers */
3648   /* and decides later whether it is worth it */
3649   min = (int) floatFromVal (vch = caseVals);
3650
3651   while (vch->next)
3652     {
3653       cnt++;
3654       vch = vch->next;
3655     }
3656   max = (int) floatFromVal (vch);
3657
3658   /* Exit if the range is too large to handle with a jump table. */
3659   if (1 + max - min > port->jumptableCost.maxCount)
3660     return 0;
3661
3662   switch (getSize (operandType (cond)))
3663     {
3664     case 1: sizeIndex = 0; break;
3665     case 2: sizeIndex = 1; break;
3666     case 4: sizeIndex = 2; break;
3667     default: return 0;
3668     }
3669
3670   /* Compute the size cost of the range check and subtraction. */
3671   sizeofMinCost = 0;
3672   sizeofZeroMinCost = 0;
3673   sizeofMaxCost = 0;
3674   if (needRangeCheck)
3675     {
3676       if (!(min==0 && IS_UNSIGNED (cetype)))
3677         sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3678       if (!IS_UNSIGNED (cetype))
3679         sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3680       sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3681     }
3682   if (min)
3683     sizeofMinCost += port->jumptableCost.sizeofSubtract;
3684
3685   /* If the size cost of handling a non-zero minimum exceeds the */
3686   /* cost of extending the range down to zero, then it might be */
3687   /* better to extend the range to zero. */
3688   if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3689                  >= (min * port->jumptableCost.sizeofElement))
3690     {
3691       /* Only extend the jump table if it would still be manageable. */
3692       if (1 + max <= port->jumptableCost.maxCount)
3693         {
3694           min = 0;
3695           if (IS_UNSIGNED (cetype))
3696             sizeofMinCost = 0;
3697           else
3698             sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3699         }
3700     }
3701
3702   /* Compute the total size cost of a jump table. */
3703   sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3704                      + port->jumptableCost.sizeofDispatch
3705                      + sizeofMinCost + sizeofMaxCost;
3706
3707   /* Compute the total size cost of a match & jump sequence */
3708   sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3709
3710   /* If the size cost of the jump table is uneconomical then exit */
3711   if (sizeofMatchJump <  sizeofJumpTable)
3712     return 0;
3713
3714   /* The jump table is preferable. */
3715
3716   /* First, a label for the default or missing cases. */
3717   if (tree->values.switchVals.swDefault)
3718     {
3719       SNPRINTF (buffer, sizeof(buffer),
3720                 "_default_%d",
3721                 tree->values.switchVals.swNum);
3722     }
3723   else
3724     {
3725       SNPRINTF (buffer, sizeof(buffer),
3726                 "_swBrk_%d",
3727                 tree->values.switchVals.swNum);
3728     }
3729   falseLabel = newiTempLabel (buffer);
3730
3731   /* Build the list of labels for the jump table. */
3732   vch = caseVals;
3733   t = (int) floatFromVal (vch);
3734   for (i=min; i<=max; i++)
3735     {
3736       if (vch && t==i)
3737         {
3738           /* Explicit case: make a new label for it. */
3739           SNPRINTF (buffer, sizeof(buffer),
3740                     "_case_%d_%d",
3741                     tree->values.switchVals.swNum,
3742                     i);
3743           addSet (&labels, newiTempLabel (buffer));
3744           vch = vch->next;
3745           if (vch)
3746             t = (int) floatFromVal (vch);
3747         }
3748       else
3749         {
3750           /* Implicit case: use the default label. */
3751           addSet (&labels, falseLabel);
3752         }
3753     }
3754
3755   /* first we rule out the boundary conditions */
3756   /* if only optimization says so */
3757   if (needRangeCheck)
3758     {
3759       sym_link *cetype = getSpec (operandType (cond));
3760       /* no need to check the lower bound if
3761          the condition is unsigned & minimum value is zero */
3762       if (!(min == 0 && IS_UNSIGNED (cetype)))
3763         {
3764           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3765           ic = newiCodeCondition (boundary, falseLabel, NULL);
3766           ADDTOCHAIN (ic);
3767         }
3768
3769       /* now for upper bounds */
3770       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3771       ic = newiCodeCondition (boundary, falseLabel, NULL);
3772       ADDTOCHAIN (ic);
3773     }
3774
3775   /* if the min is not zero then we no make it zero */
3776   if (min)
3777     {
3778       cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3779       if (!IS_LITERAL(getSpec(operandType(cond))))
3780         setOperandType (cond, UCHARTYPE);
3781     }
3782
3783   /* now create the jumptable */
3784   ic = newiCode (JUMPTABLE, NULL, NULL);
3785   IC_JTCOND (ic) = cond;
3786   IC_JTLABELS (ic) = labels;
3787   ADDTOCHAIN (ic);
3788   return 1;
3789 }
3790
3791 /*-----------------------------------------------------------------*/
3792 /* geniCodeSwitch - changes a switch to a if statement             */
3793 /*-----------------------------------------------------------------*/
3794 void
3795 geniCodeSwitch (ast * tree,int lvl)
3796 {
3797   iCode *ic;
3798   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3799   value *caseVals = tree->values.switchVals.swVals;
3800   symbol *trueLabel, *falseLabel;
3801
3802   /* If the condition is a literal, then just jump to the */
3803   /* appropriate case label. */
3804   if (IS_LITERAL(getSpec(operandType(cond))))
3805     {
3806       int switchVal, caseVal;
3807
3808       switchVal = (int) floatFromVal (cond->operand.valOperand);
3809       while (caseVals)
3810         {
3811           caseVal = (int) floatFromVal (caseVals);
3812           if (caseVal == switchVal)
3813             {
3814               SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3815                         tree->values.switchVals.swNum, caseVal);
3816               trueLabel = newiTempLabel (buffer);
3817               geniCodeGoto (trueLabel);
3818               goto jumpTable;
3819             }
3820           caseVals = caseVals->next;
3821         }
3822       goto defaultOrBreak;
3823     }
3824
3825   /* If cond is volatile, it might change while we are trying to */
3826   /* find the matching case. To avoid this possibility, make a   */
3827   /* non-volatile copy to use instead. */
3828   if (IS_OP_VOLATILE (cond))
3829     {
3830       operand * newcond;
3831       iCode * ic;
3832
3833       newcond = newiTempOperand (operandType (cond), TRUE);
3834       newcond->isvolatile = 0;
3835       ic = newiCode ('=', NULL, cond);
3836       IC_RESULT (ic) = newcond;
3837       ADDTOCHAIN (ic);
3838       cond = newcond;
3839     }
3840
3841   /* if we can make this a jump table */
3842   if (geniCodeJumpTable (cond, caseVals, tree))
3843     goto jumpTable;             /* no need for the comparison */
3844
3845   /* for the cases defined do */
3846   while (caseVals)
3847     {
3848
3849       operand *compare = geniCodeLogic (cond,
3850                                         operandFromValue (caseVals),
3851                                         EQ_OP);
3852
3853       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3854                tree->values.switchVals.swNum,
3855                (int) floatFromVal (caseVals));
3856       trueLabel = newiTempLabel (buffer);
3857
3858       ic = newiCodeCondition (compare, trueLabel, NULL);
3859       ADDTOCHAIN (ic);
3860       caseVals = caseVals->next;
3861     }
3862
3863
3864 defaultOrBreak:
3865   /* if default is present then goto break else break */
3866   if (tree->values.switchVals.swDefault)
3867     {
3868         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3869     }
3870   else
3871     {
3872         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3873     }
3874
3875   falseLabel = newiTempLabel (buffer);
3876   geniCodeGoto (falseLabel);
3877
3878 jumpTable:
3879   ast2iCode (tree->right,lvl+1);
3880 }
3881
3882 /*-----------------------------------------------------------------*/
3883 /* geniCodeInline - intermediate code for inline assembler         */
3884 /*-----------------------------------------------------------------*/
3885 static void
3886 geniCodeInline (ast * tree)
3887 {
3888   iCode *ic;
3889
3890   ic = newiCode (INLINEASM, NULL, NULL);
3891   IC_INLINE (ic) = tree->values.inlineasm;
3892   ADDTOCHAIN (ic);
3893 }
3894
3895 /*-----------------------------------------------------------------*/
3896 /* geniCodeArrayInit - intermediate code for array initializer     */
3897 /*-----------------------------------------------------------------*/
3898 static void
3899 geniCodeArrayInit (ast * tree, operand *array)
3900 {
3901   iCode *ic;
3902
3903   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3904     ic = newiCode (ARRAYINIT, array, NULL);
3905     IC_ARRAYILIST (ic) = tree->values.constlist;
3906   } else {
3907     operand *left=newOperand(), *right=newOperand();
3908     left->type=right->type=SYMBOL;
3909     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3910     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3911     ic = newiCode (ARRAYINIT, left, right);
3912   }
3913   ADDTOCHAIN (ic);
3914 }
3915
3916 /*-----------------------------------------------------------------*/
3917 /* geniCodeCritical - intermediate code for a critical statement   */
3918 /*-----------------------------------------------------------------*/
3919 static void
3920 geniCodeCritical (ast *tree, int lvl)
3921 {
3922   iCode *ic;
3923   operand *op = NULL;
3924   sym_link *type;
3925
3926   if (!options.stackAuto)
3927     {
3928       type = newLink(SPECIFIER);
3929       SPEC_VOLATILE(type) = 1;
3930       SPEC_NOUN(type) = V_BIT;
3931       SPEC_SCLS(type) = S_BIT;
3932       SPEC_BLEN(type) = 1;
3933       SPEC_BSTR(type) = 0;
3934       op = newiTempOperand(type, 1);
3935     }
3936
3937   /* If op is NULL, the original interrupt state will saved on */
3938   /* the stack. Otherwise, it will be saved in op. */
3939
3940   /* Generate a save of the current interrupt state & disable */
3941   ic = newiCode (CRITICAL, NULL, NULL);
3942   IC_RESULT (ic) = op;
3943   ADDTOCHAIN (ic);
3944
3945   /* Generate the critical code sequence */
3946   if (tree->left && tree->left->type == EX_VALUE)
3947     geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3948   else
3949     ast2iCode (tree->left,lvl+1);
3950
3951   /* Generate a restore of the original interrupt state */
3952   ic = newiCode (ENDCRITICAL, NULL, op);
3953   ADDTOCHAIN (ic);
3954 }
3955
3956 /*-----------------------------------------------------------------*/
3957 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3958 /* particular case. Ie : assigning or dereferencing array or ptr   */
3959 /*-----------------------------------------------------------------*/
3960 set * lvaluereqSet = NULL;
3961 typedef struct lvalItem
3962   {
3963     int req;
3964     int lvl;
3965   }
3966 lvalItem;
3967
3968 /*-----------------------------------------------------------------*/
3969 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3970 /*-----------------------------------------------------------------*/
3971 void addLvaluereq(int lvl)
3972 {
3973   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3974   lpItem->req=1;
3975   lpItem->lvl=lvl;
3976   addSetHead(&lvaluereqSet,lpItem);
3977
3978 }
3979 /*-----------------------------------------------------------------*/
3980 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3981 /*-----------------------------------------------------------------*/
3982 void delLvaluereq()
3983 {
3984   lvalItem * lpItem;
3985   lpItem = getSet(&lvaluereqSet);
3986   if(lpItem) Safe_free(lpItem);
3987 }
3988 /*-----------------------------------------------------------------*/
3989 /* clearLvaluereq - clear lvalreq flag                             */
3990 /*-----------------------------------------------------------------*/
3991 void clearLvaluereq()
3992 {
3993   lvalItem * lpItem;
3994   lpItem = peekSet(lvaluereqSet);
3995   if(lpItem) lpItem->req = 0;
3996 }
3997 /*-----------------------------------------------------------------*/
3998 /* getLvaluereq - get the last lvalreq level                       */
3999 /*-----------------------------------------------------------------*/
4000 int getLvaluereqLvl()
4001 {
4002   lvalItem * lpItem;
4003   lpItem = peekSet(lvaluereqSet);
4004   if(lpItem) return lpItem->lvl;
4005   return 0;
4006 }
4007 /*-----------------------------------------------------------------*/
4008 /* isLvaluereq - is lvalreq valid for this level ?                 */
4009 /*-----------------------------------------------------------------*/
4010 int isLvaluereq(int lvl)
4011 {
4012   lvalItem * lpItem;
4013   lpItem = peekSet(lvaluereqSet);
4014   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
4015   return 0;
4016 }
4017
4018 /*-----------------------------------------------------------------*/
4019 /* ast2iCode - creates an icodeList from an ast                    */
4020 /*-----------------------------------------------------------------*/
4021 operand *
4022 ast2iCode (ast * tree,int lvl)
4023 {
4024   operand *left = NULL;
4025   operand *right = NULL;
4026   if (!tree)
4027     return NULL;
4028
4029   /* set the global variables for filename & line number */
4030   if (tree->filename)
4031     filename = tree->filename;
4032   if (tree->lineno)
4033     lineno = tree->lineno;
4034   if (tree->block)
4035     block = tree->block;
4036   if (tree->level)
4037     scopeLevel = tree->level;
4038   if (tree->seqPoint)
4039     seqPoint = tree->seqPoint;
4040
4041   if (tree->type == EX_VALUE)
4042     return operandFromValue (tree->opval.val);
4043
4044   if (tree->type == EX_LINK)
4045     return operandFromLink (tree->opval.lnk);
4046
4047   /* if we find a nullop */
4048   if (tree->type == EX_OP &&
4049      (tree->opval.op == NULLOP ||
4050      tree->opval.op == BLOCK))
4051     {
4052       if (tree->left && tree->left->type == EX_VALUE)
4053         geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4054       else
4055         ast2iCode (tree->left,lvl+1);
4056       if (tree->right && tree->right->type == EX_VALUE)
4057         geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4058       else
4059         ast2iCode (tree->right,lvl+1);
4060       return NULL;
4061     }
4062
4063   /* special cases for not evaluating */
4064   if (tree->opval.op != ':' &&
4065       tree->opval.op != '?' &&
4066       tree->opval.op != CALL &&
4067       tree->opval.op != IFX &&
4068       tree->opval.op != AND_OP &&
4069       tree->opval.op != OR_OP &&
4070       tree->opval.op != LABEL &&
4071       tree->opval.op != GOTO &&
4072       tree->opval.op != SWITCH &&
4073       tree->opval.op != FUNCTION &&
4074       tree->opval.op != INLINEASM &&
4075       tree->opval.op != CRITICAL)
4076     {
4077
4078         if (IS_ASSIGN_OP (tree->opval.op) ||
4079            IS_DEREF_OP (tree) ||
4080            (tree->opval.op == '&' && !tree->right) ||
4081            tree->opval.op == PTR_OP)
4082           {
4083             addLvaluereq(lvl);
4084             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4085                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4086               clearLvaluereq();
4087
4088             left = operandFromAst (tree->left,lvl);
4089             delLvaluereq();
4090             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4091               left = geniCodeRValue (left, TRUE);
4092           }
4093         else
4094           {
4095             left = operandFromAst (tree->left,lvl);
4096           }
4097         if (tree->opval.op == INC_OP ||
4098             tree->opval.op == DEC_OP)
4099           {
4100             addLvaluereq(lvl);
4101             right = operandFromAst (tree->right,lvl);
4102             delLvaluereq();
4103           }
4104         else
4105           {
4106             right = operandFromAst (tree->right,lvl);
4107           }
4108       }
4109
4110   /* now depending on the type of operand */
4111   /* this will be a biggy                 */
4112   switch (tree->opval.op)
4113     {
4114
4115     case '[':                   /* array operation */
4116       {
4117         //sym_link *ltype = operandType (left);
4118         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4119         left = geniCodeRValue (left, FALSE);
4120         right = geniCodeRValue (right, TRUE);
4121       }
4122
4123       return geniCodeArray (left, right,lvl);
4124
4125     case '.':                   /* structure dereference */
4126       if (IS_PTR (operandType (left)))
4127         left = geniCodeRValue (left, TRUE);
4128       else
4129         left = geniCodeRValue (left, FALSE);
4130
4131       return geniCodeStruct (left, right, tree->lvalue);
4132
4133     case PTR_OP:                /* structure pointer dereference */
4134       {
4135         sym_link *pType;
4136         pType = operandType (left);
4137         left = geniCodeRValue (left, TRUE);
4138
4139         setOClass (pType, getSpec (operandType (left)));
4140       }
4141
4142       return geniCodeStruct (left, right, tree->lvalue);
4143
4144     case INC_OP:                /* increment operator */
4145       if (left)
4146         return geniCodePostInc (left);
4147       else
4148         return geniCodePreInc (right, tree->lvalue);
4149
4150     case DEC_OP:                /* decrement operator */
4151       if (left)
4152         return geniCodePostDec (left);
4153       else
4154         return geniCodePreDec (right, tree->lvalue);
4155
4156     case '&':                   /* bitwise and or address of operator */
4157       if (right)
4158         {                       /* this is a bitwise operator   */
4159           left = geniCodeRValue (left, FALSE);
4160           right = geniCodeRValue (right, FALSE);
4161           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4162         }
4163       else
4164         return geniCodeAddressOf (left);
4165
4166     case '|':                   /* bitwise or & xor */
4167     case '^':
4168       return geniCodeBitwise (geniCodeRValue (left, FALSE),
4169                               geniCodeRValue (right, FALSE),
4170                               tree->opval.op,
4171                               tree->ftype);
4172
4173     case '/':
4174       return geniCodeDivision (geniCodeRValue (left, FALSE),
4175                                geniCodeRValue (right, FALSE),
4176                                getResultTypeFromType (tree->ftype));
4177
4178     case '%':
4179       return geniCodeModulus (geniCodeRValue (left, FALSE),
4180                               geniCodeRValue (right, FALSE),
4181                               getResultTypeFromType (tree->ftype));
4182     case '*':
4183       if (right)
4184         return geniCodeMultiply (geniCodeRValue (left, FALSE),
4185                                  geniCodeRValue (right, FALSE),
4186                                  getResultTypeFromType (tree->ftype));
4187       else
4188         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4189
4190     case '-':
4191       if (right)
4192         return geniCodeSubtract (geniCodeRValue (left, FALSE),
4193                                  geniCodeRValue (right, FALSE),
4194                                  getResultTypeFromType (tree->ftype));
4195       else
4196         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4197
4198     case '+':
4199       if (right)
4200         return geniCodeAdd (geniCodeRValue (left, FALSE),
4201                             geniCodeRValue (right, FALSE),
4202                             getResultTypeFromType (tree->ftype),
4203                             lvl);
4204       else
4205         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
4206
4207     case LEFT_OP:
4208       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4209                                 geniCodeRValue (right, FALSE),
4210                                 getResultTypeFromType (tree->ftype));
4211
4212     case RIGHT_OP:
4213       return geniCodeRightShift (geniCodeRValue (left, FALSE),
4214                                  geniCodeRValue (right, FALSE));
4215     case CAST:
4216 #if 0 // this indeed needs a second thought
4217       {
4218         operand *op;
4219
4220         // let's keep this simple: get the rvalue we need
4221         op=geniCodeRValue (right, FALSE);
4222         // now cast it to whatever we want
4223         op=geniCodeCast (operandType(left), op, FALSE);
4224         // if this is going to be used as an lvalue, make it so
4225         if (tree->lvalue) {
4226           op->isaddr=1;
4227         }
4228         return op;
4229       }
4230 #else // bug #604575, is it a bug ????
4231       return geniCodeCast (operandType (left),
4232                            geniCodeRValue (right, FALSE), FALSE);
4233 #endif
4234
4235     case '~':
4236     case RRC:
4237     case RLC:
4238     case SWAP:
4239       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4240
4241     case '!':
4242     case GETHBIT:
4243       {
4244         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4245         if (!IS_BIT (operandType (op)))
4246           setOperandType (op, UCHARTYPE);
4247         return op;
4248       }
4249     case GETABIT:
4250       {
4251         operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4252                                       geniCodeRValue (right, FALSE),
4253                                       tree->opval.op);
4254         if (!IS_BIT (operandType (op)))
4255           setOperandType (op, UCHARTYPE);
4256         return op;
4257       }
4258     case GETBYTE:
4259       {
4260         operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4261                                       geniCodeRValue (right, FALSE),
4262                                       tree->opval.op);
4263         setOperandType (op, UCHARTYPE);
4264         return op;
4265       }
4266     case GETWORD:
4267       {
4268         operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
4269                                       geniCodeRValue (right, FALSE),
4270                                       tree->opval.op);
4271         setOperandType (op, UINTTYPE);
4272         return op;
4273       }
4274     case AND_OP:
4275     case OR_OP:
4276       return geniCodeLogicAndOr (tree, lvl);
4277     case '>':
4278     case '<':
4279     case LE_OP:
4280     case GE_OP:
4281     case EQ_OP:
4282     case NE_OP:
4283       /* different compilers (even different gccs) evaluate
4284          the two calls in a different order. to get the same
4285          result on all machines we have to specify a clear sequence.
4286       return geniCodeLogic (geniCodeRValue (left, FALSE),
4287                             geniCodeRValue (right, FALSE),
4288                             tree->opval.op);
4289       */
4290       {
4291         operand *leftOp, *rightOp;
4292
4293         leftOp  = geniCodeRValue (left , FALSE);
4294         rightOp = geniCodeRValue (right, FALSE);
4295
4296         return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4297       }
4298     case '?':
4299       return geniCodeConditional (tree,lvl);
4300
4301     case SIZEOF:
4302       return operandFromLit (getSize (tree->right->ftype));
4303
4304     case '=':
4305       {
4306         sym_link *rtype = operandType (right);
4307         sym_link *ltype = operandType (left);
4308         if (IS_PTR (rtype) && IS_ITEMP (right)
4309             && right->isaddr && compareType (rtype->next, ltype) == 1)
4310           right = geniCodeRValue (right, TRUE);
4311         else
4312           right = geniCodeRValue (right, FALSE);
4313
4314         return geniCodeAssign (left, right, 0, 1);
4315       }
4316     case MUL_ASSIGN:
4317       return
4318         geniCodeAssign (left,
4319                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4320                                                   FALSE),
4321                                   geniCodeRValue (right, FALSE),
4322                                   getResultTypeFromType (tree->ftype)),
4323                         0, 1);
4324
4325     case DIV_ASSIGN:
4326       return
4327         geniCodeAssign (left,
4328                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4329                                                   FALSE),
4330                                   geniCodeRValue (right, FALSE),
4331                                   getResultTypeFromType (tree->ftype)),
4332                         0, 1);
4333     case MOD_ASSIGN:
4334       return
4335         geniCodeAssign (left,
4336                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4337                                                   FALSE),
4338                                   geniCodeRValue (right, FALSE),
4339                                   getResultTypeFromType (tree->ftype)),
4340                         0, 1);
4341     case ADD_ASSIGN:
4342       {
4343         sym_link *rtype = operandType (right);
4344         sym_link *ltype = operandType (left);
4345         if (IS_PTR (rtype) && IS_ITEMP (right)
4346             && right->isaddr && compareType (rtype->next, ltype) == 1)
4347           right = geniCodeRValue (right, TRUE);
4348         else
4349           right = geniCodeRValue (right, FALSE);
4350
4351
4352         return geniCodeAssign (left,
4353                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4354                                                   FALSE),
4355                                   right,
4356                                   getResultTypeFromType (tree->ftype),
4357                                   lvl),
4358                                0, 1);
4359       }
4360     case SUB_ASSIGN:
4361       {
4362         sym_link *rtype = operandType (right);
4363         sym_link *ltype = operandType (left);
4364         if (IS_PTR (rtype) && IS_ITEMP (right)
4365             && right->isaddr && compareType (rtype->next, ltype) == 1)
4366           {
4367             right = geniCodeRValue (right, TRUE);
4368           }
4369         else
4370           {
4371             right = geniCodeRValue (right, FALSE);
4372           }
4373         return
4374           geniCodeAssign (left,
4375                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4376                                                   FALSE),
4377                                   right,
4378                                   getResultTypeFromType (tree->ftype)),
4379                           0, 1);
4380       }
4381     case LEFT_ASSIGN:
4382       return
4383         geniCodeAssign (left,
4384                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4385                                                    ,FALSE),
4386                                    geniCodeRValue (right, FALSE),
4387                                    getResultTypeFromType (tree->ftype)),
4388                         0, 1);
4389     case RIGHT_ASSIGN:
4390       return
4391         geniCodeAssign (left,
4392                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4393                                                    ,FALSE),
4394                                    geniCodeRValue (right, FALSE)), 0, 1);
4395     case AND_ASSIGN:
4396       return
4397         geniCodeAssign (left,
4398                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4399                                                   FALSE),
4400                                   geniCodeRValue (right, FALSE),
4401                                   BITWISEAND,
4402                                   operandType (left)), 0, 1);
4403     case XOR_ASSIGN:
4404       return
4405         geniCodeAssign (left,
4406                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4407                                                   FALSE),
4408                                   geniCodeRValue (right, FALSE),
4409                                   '^',
4410                                   operandType (left)), 0, 1);
4411     case OR_ASSIGN:
4412       return
4413         geniCodeAssign (left,
4414                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4415                                                    ,FALSE),
4416                                    geniCodeRValue (right, FALSE),
4417                                    '|',
4418                                    operandType (left)), 0, 1);
4419     case ',':
4420       return geniCodeRValue (right, FALSE);
4421
4422     case CALL:
4423       return geniCodeCall (ast2iCode (tree->left,lvl+1),
4424                            tree->right,lvl);
4425     case LABEL:
4426       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4427       return ast2iCode (tree->right,lvl+1);
4428
4429     case GOTO:
4430       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4431       return ast2iCode (tree->right,lvl+1);
4432
4433     case FUNCTION:
4434       geniCodeFunctionBody (tree,lvl);
4435       return NULL;
4436
4437     case RETURN:
4438       geniCodeReturn (right);
4439       return NULL;
4440
4441     case IFX:
4442       geniCodeIfx (tree,lvl);
4443       return NULL;
4444
4445     case SWITCH:
4446       geniCodeSwitch (tree,lvl);
4447       return NULL;
4448
4449     case INLINEASM:
4450       geniCodeInline (tree);
4451       return NULL;
4452
4453     case ARRAYINIT:
4454         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4455         return NULL;
4456
4457     case CRITICAL:
4458         geniCodeCritical (tree, lvl);
4459     }
4460
4461   return NULL;
4462 }
4463
4464 /*-----------------------------------------------------------------*/
4465 /* reverseICChain - gets from the list and creates a linkedlist    */
4466 /*-----------------------------------------------------------------*/
4467 iCode *
4468 reverseiCChain ()
4469 {
4470   iCode *loop = NULL;
4471   iCode *prev = NULL;
4472
4473   while ((loop = getSet (&iCodeChain)))
4474     {
4475       loop->next = prev;
4476       if (prev)
4477         prev->prev = loop;
4478       prev = loop;
4479     }
4480
4481   return prev;
4482 }
4483
4484
4485 /*-----------------------------------------------------------------*/
4486 /* iCodeFromAst - given an ast will convert it to iCode            */
4487 /*-----------------------------------------------------------------*/
4488 iCode *
4489 iCodeFromAst (ast * tree)
4490 {
4491   returnLabel = newiTempLabel ("_return");
4492   entryLabel = newiTempLabel ("_entry");
4493   ast2iCode (tree,0);
4494   return reverseiCChain ();
4495 }
4496
4497 static const char *opTypeToStr(OPTYPE op)
4498 {
4499     switch(op)
4500     {
4501       case SYMBOL: return "symbol";
4502       case VALUE: return "value";
4503       case TYPE: return "type";
4504     }
4505     return "undefined type";
4506 }
4507
4508
4509 operand *validateOpType(operand         *op,
4510                         const char      *macro,
4511                         const char      *args,
4512                         OPTYPE          type,
4513                         const char      *file,
4514                         unsigned        line)
4515 {
4516     if (op && op->type == type)
4517     {
4518         return op;
4519     }
4520     fprintf(stderr,
4521             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4522             " expected %s, got %s\n",
4523             macro, args, file, line,
4524             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4525     exit(EXIT_FAILURE);
4526     return op; // never reached, makes compiler happy.
4527 }