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