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