* device/lib/_gptrget.c,
[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 a2p%d re%d rm%d nos%d ru%d dp%d}",           /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}"  , */
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->aggr2ptr, 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 a "pointer to 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   if (!IS_AGGREGATE (ltype->next))
2420     {
2421       IC_RESULT (ic)->isaddr = 1;
2422       IC_RESULT (ic)->aggr2ptr = 1;
2423     }
2424   ADDTOCHAIN (ic);
2425
2426   return IC_RESULT (ic);
2427 }
2428
2429 /*-----------------------------------------------------------------*/
2430 /* geniCodeStruct - generates intermediate code for structures     */
2431 /*-----------------------------------------------------------------*/
2432 operand *
2433 geniCodeStruct (operand * left, operand * right, bool islval)
2434 {
2435   iCode *ic;
2436   sym_link *type = operandType (left);
2437   sym_link *etype = getSpec (type);
2438   sym_link *retype;
2439   symbol *element = getStructElement (SPEC_STRUCT (etype),
2440                                       right->operand.symOperand);
2441
2442   wassert(IS_SYMOP(right));
2443
2444   /* add the offset */
2445   ic = newiCode ('+', left, operandFromLit (element->offset));
2446
2447   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2448
2449   /* preserve the storage & output class of the struct */
2450   /* as well as the volatile attribute */
2451   retype = getSpec (operandType (IC_RESULT (ic)));
2452   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2453   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2454   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2455   SPEC_CONST (retype) |= SPEC_CONST (etype);
2456
2457   if (IS_PTR (element->type))
2458     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2459
2460   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2461
2462   ADDTOCHAIN (ic);
2463   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2464 }
2465
2466 /*-----------------------------------------------------------------*/
2467 /* geniCodePostInc - generate int code for Post increment          */
2468 /*-----------------------------------------------------------------*/
2469 operand *
2470 geniCodePostInc (operand * op)
2471 {
2472   iCode *ic;
2473   operand *rOp;
2474   sym_link *optype = operandType (op);
2475   operand *result;
2476   operand *rv = (IS_ITEMP (op) ?
2477                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2478                  op);
2479   sym_link *rvtype = operandType (rv);
2480   int size = 0;
2481
2482   /* if this is not an address we have trouble */
2483   if (!op->isaddr)
2484     {
2485       werror (E_LVALUE_REQUIRED, "++");
2486       return op;
2487     }
2488
2489   rOp = newiTempOperand (rvtype, 0);
2490   OP_SYMBOL(rOp)->noSpilLoc = 1;
2491
2492   if (IS_ITEMP (rv))
2493     OP_SYMBOL(rv)->noSpilLoc = 1;
2494
2495   geniCodeAssign (rOp, rv, 0, 0);
2496
2497   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2498   if (IS_FLOAT (rvtype))
2499     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2500   else
2501     ic = newiCode ('+', rv, operandFromLit (size));
2502
2503   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2504   ADDTOCHAIN (ic);
2505
2506   geniCodeAssign (op, result, 0, 0);
2507
2508   return rOp;
2509
2510 }
2511
2512 /*-----------------------------------------------------------------*/
2513 /* geniCodePreInc - generate code for preIncrement                 */
2514 /*-----------------------------------------------------------------*/
2515 operand *
2516 geniCodePreInc (operand * op, bool lvalue)
2517 {
2518   iCode *ic;
2519   sym_link *optype = operandType (op);
2520   operand *rop = (IS_ITEMP (op) ?
2521                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2522                   op);
2523   sym_link *roptype = operandType (rop);
2524   operand *result;
2525   int size = 0;
2526
2527   if (!op->isaddr)
2528     {
2529       werror (E_LVALUE_REQUIRED, "++");
2530       return op;
2531     }
2532
2533
2534   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2535   if (IS_FLOAT (roptype))
2536     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2537   else
2538     ic = newiCode ('+', rop, operandFromLit (size));
2539   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2540   ADDTOCHAIN (ic);
2541
2542   (void) geniCodeAssign (op, result, 0, 0);
2543   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2544     return op;
2545   else
2546     return result;
2547 }
2548
2549 /*-----------------------------------------------------------------*/
2550 /* geniCodePostDec - generates code for Post decrement             */
2551 /*-----------------------------------------------------------------*/
2552 operand *
2553 geniCodePostDec (operand * op)
2554 {
2555   iCode *ic;
2556   operand *rOp;
2557   sym_link *optype = operandType (op);
2558   operand *result;
2559   operand *rv = (IS_ITEMP (op) ?
2560                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2561                  op);
2562   sym_link *rvtype = operandType (rv);
2563   int size = 0;
2564
2565   /* if this is not an address we have trouble */
2566   if (!op->isaddr)
2567     {
2568       werror (E_LVALUE_REQUIRED, "--");
2569       return op;
2570     }
2571
2572   rOp = newiTempOperand (rvtype, 0);
2573   OP_SYMBOL(rOp)->noSpilLoc = 1;
2574
2575   if (IS_ITEMP (rv))
2576     OP_SYMBOL(rv)->noSpilLoc = 1;
2577
2578   geniCodeAssign (rOp, rv, 0, 0);
2579
2580   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2581   if (IS_FLOAT (rvtype))
2582     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2583   else
2584     ic = newiCode ('-', rv, operandFromLit (size));
2585
2586   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2587   ADDTOCHAIN (ic);
2588
2589   geniCodeAssign (op, result, 0, 0);
2590
2591   return rOp;
2592
2593 }
2594
2595 /*-----------------------------------------------------------------*/
2596 /* geniCodePreDec - generate code for pre  decrement               */
2597 /*-----------------------------------------------------------------*/
2598 operand *
2599 geniCodePreDec (operand * op, bool lvalue)
2600 {
2601   iCode *ic;
2602   sym_link *optype = operandType (op);
2603   operand *rop = (IS_ITEMP (op) ?
2604                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2605                   op);
2606   sym_link *roptype = operandType (rop);
2607   operand *result;
2608   int size = 0;
2609
2610   if (!op->isaddr)
2611     {
2612       werror (E_LVALUE_REQUIRED, "--");
2613       return op;
2614     }
2615
2616
2617   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2618   if (IS_FLOAT (roptype))
2619     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2620   else
2621     ic = newiCode ('-', rop, operandFromLit (size));
2622   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2623   ADDTOCHAIN (ic);
2624
2625   (void) geniCodeAssign (op, result, 0, 0);
2626   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2627     return op;
2628   else
2629     return result;
2630 }
2631
2632
2633 /*-----------------------------------------------------------------*/
2634 /* geniCodeBitwise - gen int code for bitWise  operators           */
2635 /*-----------------------------------------------------------------*/
2636 operand *
2637 geniCodeBitwise (operand * left, operand * right,
2638                  int oper, sym_link * resType)
2639 {
2640   iCode *ic;
2641
2642   left = geniCodeCast (resType, left, TRUE);
2643   right = geniCodeCast (resType, right, TRUE);
2644
2645   ic = newiCode (oper, left, right);
2646   IC_RESULT (ic) = newiTempOperand (resType, 0);
2647
2648   ADDTOCHAIN (ic);
2649   return IC_RESULT (ic);
2650 }
2651
2652 /*-----------------------------------------------------------------*/
2653 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2654 /*-----------------------------------------------------------------*/
2655 operand *
2656 geniCodeAddressOf (operand * op)
2657 {
2658   iCode *ic;
2659   sym_link *p;
2660   sym_link *optype = operandType (op);
2661   sym_link *opetype = getSpec (optype);
2662
2663   if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2664     {
2665       op = operandFromOperand (op);
2666       op->isaddr = 0;
2667       return op;
2668     }
2669   
2670   /* lvalue check already done in decorateType */
2671   /* this must be a lvalue */
2672 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2673 /*  werror (E_LVALUE_REQUIRED,"&"); */
2674 /*  return op; */
2675 /*     } */
2676
2677   p = newLink (DECLARATOR);
2678
2679   /* set the pointer depending on the storage class */
2680   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2681
2682   p->next = copyLinkChain (optype);
2683
2684   /* if already a temp */
2685   if (IS_ITEMP (op))
2686     {
2687       setOperandType (op, p);
2688       op->isaddr = 0;
2689       return op;
2690     }
2691
2692   /* other wise make this of the type coming in */
2693   ic = newiCode (ADDRESS_OF, op, NULL);
2694   IC_RESULT (ic) = newiTempOperand (p, 1);
2695   IC_RESULT (ic)->isaddr = 0;
2696   ADDTOCHAIN (ic);
2697   return IC_RESULT (ic);
2698 }
2699 /*-----------------------------------------------------------------*/
2700 /* setOClass - sets the output class depending on the pointer type */
2701 /*-----------------------------------------------------------------*/
2702 void 
2703 setOClass (sym_link * ptr, sym_link * spec)
2704 {
2705   switch (DCL_TYPE (ptr))
2706     {
2707     case POINTER:
2708       SPEC_OCLS (spec) = data;
2709       break;
2710
2711     case GPOINTER:
2712       SPEC_OCLS (spec) = generic;
2713       break;
2714
2715     case FPOINTER:
2716       SPEC_OCLS (spec) = xdata;
2717       break;
2718
2719     case CPOINTER:
2720       SPEC_OCLS (spec) = code;
2721       break;
2722
2723     case IPOINTER:
2724       SPEC_OCLS (spec) = idata;
2725       break;
2726
2727     case PPOINTER:
2728       SPEC_OCLS (spec) = xstack;
2729       break;
2730
2731     case EEPPOINTER:
2732       SPEC_OCLS (spec) = eeprom;
2733       break;
2734
2735     default:
2736       break;
2737
2738     }
2739 }
2740
2741 /*-----------------------------------------------------------------*/
2742 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2743 /*-----------------------------------------------------------------*/
2744 operand *
2745 geniCodeDerefPtr (operand * op,int lvl)
2746 {
2747   sym_link *rtype, *retype;
2748   sym_link *optype = operandType (op);
2749
2750   // if this is an array then array access
2751   if (IS_ARRAY (optype)) {
2752     // don't worry, this will be optimized out later
2753     return geniCodeArray (op, operandFromLit (0), lvl);
2754   }
2755
2756   // just in case someone screws up
2757   wassert (IS_PTR (optype));
2758
2759   if (IS_TRUE_SYMOP (op))
2760     {
2761       op->isaddr = 1;
2762       op = geniCodeRValue (op, TRUE);
2763     }
2764
2765   /* now get rid of the pointer part */
2766   if (isLvaluereq(lvl) && IS_ITEMP (op))
2767     {
2768       retype = getSpec (rtype = copyLinkChain (optype));
2769     }
2770   else
2771     {
2772       retype = getSpec (rtype = copyLinkChain (optype->next));
2773       /* outputclass needs 2b updated */
2774       setOClass (optype, retype);
2775     }
2776   
2777   op->isGptr = IS_GENPTR (optype);
2778
2779   op->isaddr = (IS_PTR (rtype) ||
2780                 IS_STRUCT (rtype) ||
2781                 IS_INT (rtype) ||
2782                 IS_CHAR (rtype) ||
2783                 IS_FLOAT (rtype));
2784
2785   if (!isLvaluereq(lvl))
2786     op = geniCodeRValue (op, TRUE);
2787
2788   setOperandType (op, rtype);
2789
2790   return op;
2791 }
2792
2793 /*-----------------------------------------------------------------*/
2794 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2795 /*-----------------------------------------------------------------*/
2796 operand *
2797 geniCodeUnaryMinus (operand * op)
2798 {
2799   iCode *ic;
2800   sym_link *optype = operandType (op);
2801
2802   if (IS_LITERAL (optype))
2803     return operandFromLit (-floatFromVal (op->operand.valOperand));
2804
2805   ic = newiCode (UNARYMINUS, op, NULL);
2806   IC_RESULT (ic) = newiTempOperand (optype, 0);
2807   ADDTOCHAIN (ic);
2808   return IC_RESULT (ic);
2809 }
2810
2811 /*-----------------------------------------------------------------*/
2812 /* geniCodeLeftShift - gen i code for left shift                   */
2813 /*-----------------------------------------------------------------*/
2814 operand *
2815 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2816 {
2817   iCode *ic;
2818   sym_link *resType;
2819
2820   ic = newiCode (LEFT_OP, left, right);
2821
2822   resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2823   IC_RESULT (ic) = newiTempOperand (resType, 0);
2824   ADDTOCHAIN (ic);
2825   return IC_RESULT (ic);
2826 }
2827
2828 /*-----------------------------------------------------------------*/
2829 /* geniCodeRightShift - gen i code for right shift                 */
2830 /*-----------------------------------------------------------------*/
2831 operand *
2832 geniCodeRightShift (operand * left, operand * right)
2833 {
2834   iCode *ic;
2835
2836   ic = newiCode (RIGHT_OP, left, right);
2837   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2838   ADDTOCHAIN (ic);
2839   return IC_RESULT (ic);
2840 }
2841
2842 /*-----------------------------------------------------------------*/
2843 /* geniCodeLogic- logic code                                       */
2844 /*-----------------------------------------------------------------*/
2845 static operand *
2846 geniCodeLogic (operand * left, operand * right, int op)
2847 {
2848   iCode *ic;
2849   sym_link *ctype;
2850   sym_link *rtype = operandType (right);
2851   sym_link *ltype = operandType (left);
2852
2853   /* left is integral type and right is literal then
2854      check if the literal value is within bounds */
2855   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2856     {
2857       checkConstantRange(ltype,
2858                          OP_VALUE(right), "compare operation", 1);
2859     }
2860
2861   /* if one operand is a pointer and the other is a literal generic void pointer,
2862      change the type of the literal generic void pointer to match the other pointer */
2863   if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2864       && IS_PTR (rtype) && !IS_GENPTR(rtype))
2865     {
2866       /* find left's definition */
2867       ic = (iCode *) setFirstItem (iCodeChain);
2868       while (ic)
2869         {
2870           if (((ic->op == CAST) || (ic->op == '='))
2871               && isOperandEqual(left, IC_RESULT (ic)))
2872             break;
2873           else
2874             ic = setNextItem (iCodeChain);
2875         }
2876       /* if casting literal to generic pointer, then cast to rtype instead */
2877       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2878         {
2879           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2880           ltype = operandType(left);
2881         }
2882     }
2883   if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2884       && IS_PTR (ltype) && !IS_GENPTR(ltype))
2885     {
2886       /* find right's definition */
2887       ic = (iCode *) setFirstItem (iCodeChain);
2888       while (ic)
2889         {
2890           if (((ic->op == CAST) || (ic->op == '='))
2891               && isOperandEqual(right, IC_RESULT (ic)))
2892             break;
2893           else
2894             ic = setNextItem (iCodeChain);
2895         }
2896       /* if casting literal to generic pointer, then cast to rtype instead */
2897       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2898         {
2899           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2900           rtype = operandType(right);
2901         }
2902     }
2903
2904   ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
2905
2906   ic = newiCode (op, left, right);
2907   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2908
2909   /* if comparing float
2910      and not a '==' || '!=' || '&&' || '||' (these
2911      will be inlined */
2912   if (IS_FLOAT(ctype) &&
2913       op != EQ_OP &&
2914       op != NE_OP &&
2915       op != AND_OP &&
2916       op != OR_OP)
2917    ic->supportRtn = 1;
2918
2919   ADDTOCHAIN (ic);
2920   return IC_RESULT (ic);
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* geniCodeLogicAndOr - && || operations                           */
2925 /*-----------------------------------------------------------------*/
2926 static operand *
2927 geniCodeLogicAndOr (ast *tree, int lvl)
2928 {
2929   iCode *ic;
2930   symbol *falseLabel = newiTempLabel (NULL);
2931   symbol *trueLabel  = newiTempLabel (NULL);
2932   symbol *exitLabel  = newiTempLabel (NULL);
2933   operand *op, *result, *condition;
2934
2935   /* AND_OP and OR_OP are no longer generated because of bug-905492.
2936      They can be reenabled by executing the following block. If you find
2937      a decent optimization you could start right here:
2938   */
2939 #if 0
2940   if (0)
2941     {
2942        operand *leftOp, *rightOp;
2943
2944        leftOp  = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
2945        rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
2946
2947        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
2948     }
2949 #endif
2950
2951   /* generate two IFX for the '&&' or '||' op */
2952
2953   /* evaluate left operand */
2954   condition = ast2iCode (tree->left, lvl + 1);
2955   op = geniCodeRValue (condition, FALSE);
2956
2957   /* test left operand */
2958   if (tree->opval.op == AND_OP)
2959     ic = newiCodeCondition (op, NULL, falseLabel);
2960   else /* OR_OP */
2961     ic = newiCodeCondition (op, trueLabel, NULL);
2962   ADDTOCHAIN (ic);
2963   
2964   /* evaluate right operand */
2965   condition = ast2iCode (tree->right, lvl + 1);
2966   op = geniCodeRValue (condition, FALSE);
2967   
2968   /* test right operand */
2969   ic = newiCodeCondition (op, trueLabel, NULL);
2970   ADDTOCHAIN (ic);
2971   
2972   /* store 0 or 1 in result */
2973   result = newiTempOperand (newCharLink(), 1);
2974   
2975   geniCodeLabel (falseLabel);
2976   geniCodeAssign (result, operandFromLit (0), 0, 0);
2977   /* generate an unconditional goto */
2978   geniCodeGoto (exitLabel);
2979
2980   geniCodeLabel (trueLabel);
2981   geniCodeAssign (result, operandFromLit (1), 0, 0);
2982
2983   geniCodeLabel (exitLabel);
2984
2985   return result;
2986 }
2987
2988 /*-----------------------------------------------------------------*/
2989 /* geniCodeUnary - for a a generic unary operation                 */
2990 /*-----------------------------------------------------------------*/
2991 operand *
2992 geniCodeUnary (operand * op, int oper)
2993 {
2994   iCode *ic = newiCode (oper, op, NULL);
2995
2996   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2997   ADDTOCHAIN (ic);
2998   return IC_RESULT (ic);
2999 }
3000
3001 /*-----------------------------------------------------------------*/
3002 /* geniCodeConditional - geniCode for '?' ':' operation            */
3003 /*-----------------------------------------------------------------*/
3004 operand *
3005 geniCodeConditional (ast * tree,int lvl)
3006 {
3007   iCode *ic;
3008   symbol *falseLabel = newiTempLabel (NULL);
3009   symbol *exitLabel = newiTempLabel (NULL);
3010   operand *cond = ast2iCode (tree->left,lvl+1);
3011   operand *true, *false, *result;
3012
3013   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3014                           NULL, falseLabel);
3015   ADDTOCHAIN (ic);
3016
3017   true = ast2iCode (tree->right->left,lvl+1);
3018
3019   /* move the value to a new Operand */
3020   result = newiTempOperand (tree->right->ftype, 0);
3021   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3022
3023   /* generate an unconditional goto */
3024   geniCodeGoto (exitLabel);
3025
3026   /* now for the right side */
3027   geniCodeLabel (falseLabel);
3028
3029   false = ast2iCode (tree->right->right,lvl+1);
3030   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3031
3032   /* create the exit label */
3033   geniCodeLabel (exitLabel);
3034
3035   return result;
3036 }
3037
3038 /*-----------------------------------------------------------------*/
3039 /* geniCodeAssign - generate code for assignment                   */
3040 /*-----------------------------------------------------------------*/
3041 operand *
3042 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3043 {
3044   iCode *ic;
3045   sym_link *ltype = operandType (left);
3046   sym_link *rtype = operandType (right);
3047
3048   if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3049     {
3050       werror (E_LVALUE_REQUIRED, "assignment");
3051       return left;
3052     }
3053
3054   /* left is integral type and right is literal then
3055      check if the literal value is within bounds */
3056   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3057     {
3058       checkConstantRange(ltype, 
3059                          OP_VALUE(right), "= operation", 0);
3060     }
3061
3062   /* if the left & right type don't exactly match */
3063   /* if pointer set then make sure the check is
3064      done with the type & not the pointer */
3065   /* then cast rights type to left */
3066
3067   /* first check the type for pointer assignement */
3068   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3069       compareType (ltype, rtype) <= 0)
3070     {
3071       if (compareType (ltype->next, rtype) < 0)
3072         right = geniCodeCast (ltype->next, right, TRUE);
3073     }
3074   else if (compareType (ltype, rtype) < 0)
3075     right = geniCodeCast (ltype, right, TRUE);
3076
3077   /* If left is a true symbol & ! volatile
3078      create an assignment to temporary for
3079      the right & then assign this temporary
3080      to the symbol. This is SSA (static single
3081      assignment). Isn't it simple and folks have
3082      published mountains of paper on it */
3083   if (IS_TRUE_SYMOP (left) &&
3084       !isOperandVolatile (left, FALSE) &&
3085       isOperandGlobal (left))
3086     {
3087       symbol *sym = NULL;
3088
3089       if (IS_TRUE_SYMOP (right))
3090         sym = OP_SYMBOL (right);
3091       ic = newiCode ('=', NULL, right);
3092       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3093       SPIL_LOC (right) = sym;
3094       ADDTOCHAIN (ic);
3095     }
3096
3097   ic = newiCode ('=', NULL, right);
3098   IC_RESULT (ic) = left;
3099   ADDTOCHAIN (ic);
3100
3101   /* if left isgptr flag is set then support
3102      routine will be required */
3103   if (left->isGptr)
3104     ic->supportRtn = 1;
3105
3106   ic->nosupdate = nosupdate;
3107   return left;
3108 }
3109
3110 /*-----------------------------------------------------------------*/
3111 /* geniCodeDummyRead - generate code for dummy read                */
3112 /*-----------------------------------------------------------------*/
3113 static void
3114 geniCodeDummyRead (operand * op)
3115 {
3116   iCode *ic;
3117   sym_link *type = operandType (op);
3118
3119   if (!IS_VOLATILE(type))
3120     return;
3121     
3122   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3123   ADDTOCHAIN (ic);
3124
3125   ic->nosupdate = 1;
3126 }
3127
3128 /*-----------------------------------------------------------------*/
3129 /* geniCodeSEParms - generate code for side effecting fcalls       */
3130 /*-----------------------------------------------------------------*/
3131 static void 
3132 geniCodeSEParms (ast * parms,int lvl)
3133 {
3134   if (!parms)
3135     return;
3136
3137   if (parms->type == EX_OP && parms->opval.op == PARAM)
3138     {
3139       geniCodeSEParms (parms->left,lvl);
3140       geniCodeSEParms (parms->right,lvl);
3141       return;
3142     }
3143
3144   /* hack don't like this but too lazy to think of
3145      something better */
3146   if (IS_ADDRESS_OF_OP (parms))
3147     parms->left->lvalue = 1;
3148
3149   if (IS_CAST_OP (parms) &&
3150       IS_PTR (parms->ftype) &&
3151       IS_ADDRESS_OF_OP (parms->right))
3152     parms->right->left->lvalue = 1;
3153
3154   parms->opval.oprnd = 
3155     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3156                 
3157   parms->type = EX_OPERAND;
3158   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3159                 SPEC_ARGREG(parms->ftype);
3160 }
3161
3162 /*-----------------------------------------------------------------*/
3163 /* geniCodeParms - generates parameters                            */
3164 /*-----------------------------------------------------------------*/
3165 value *
3166 geniCodeParms (ast * parms, value *argVals, int *stack, 
3167                sym_link * ftype, int lvl)
3168 {
3169   iCode *ic;
3170   operand *pval;
3171
3172   if (!parms)
3173     return argVals;
3174
3175   if (argVals==NULL) {
3176     // first argument
3177     argVals = FUNC_ARGS (ftype);
3178   }
3179
3180   /* if this is a param node then do the left & right */
3181   if (parms->type == EX_OP && parms->opval.op == PARAM)
3182     {
3183       argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3184       argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3185       return argVals;
3186     }
3187
3188   /* get the parameter value */
3189   if (parms->type == EX_OPERAND)
3190     pval = parms->opval.oprnd;
3191   else
3192     {
3193       /* maybe this else should go away ?? */
3194       /* hack don't like this but too lazy to think of
3195          something better */
3196       if (IS_ADDRESS_OF_OP (parms))
3197         parms->left->lvalue = 1;
3198
3199       if (IS_CAST_OP (parms) &&
3200           IS_PTR (parms->ftype) &&
3201           IS_ADDRESS_OF_OP (parms->right))
3202         parms->right->left->lvalue = 1;
3203
3204       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3205     }
3206
3207   /* if register parm then make it a send */
3208   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3209       IFFUNC_ISBUILTIN(ftype))
3210     {
3211       ic = newiCode (SEND, pval, NULL);
3212       ic->argreg = SPEC_ARGREG(parms->etype);
3213       ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3214       ADDTOCHAIN (ic);
3215     }
3216   else
3217     {
3218       /* now decide whether to push or assign */
3219       if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3220         {
3221
3222           /* assign */
3223           operand *top = operandFromSymbol (argVals->sym);
3224           /* clear useDef and other bitVectors */
3225           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3226           geniCodeAssign (top, pval, 1, 0);
3227         }
3228       else
3229         {
3230           sym_link *p = operandType (pval);
3231           /* push */
3232           ic = newiCode (IPUSH, pval, NULL);
3233           ic->parmPush = 1;
3234           /* update the stack adjustment */
3235           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3236           ADDTOCHAIN (ic);
3237         }
3238     }
3239
3240   argVals=argVals->next;
3241   return argVals;
3242 }
3243
3244 /*-----------------------------------------------------------------*/
3245 /* geniCodeCall - generates temp code for calling                  */
3246 /*-----------------------------------------------------------------*/
3247 operand *
3248 geniCodeCall (operand * left, ast * parms,int lvl)
3249 {
3250   iCode *ic;
3251   operand *result;
3252   sym_link *type, *etype;
3253   sym_link *ftype;
3254   int stack = 0;
3255
3256   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
3257       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3258     werror (E_FUNCTION_EXPECTED);
3259     return operandFromValue(valueFromLit(0));
3260   }
3261
3262   /* take care of parameters with side-effecting
3263      function calls in them, this is required to take care
3264      of overlaying function parameters */
3265   geniCodeSEParms (parms,lvl);
3266
3267   ftype = operandType (left);
3268   if (IS_CODEPTR (ftype))
3269     ftype = ftype->next;
3270     
3271   /* first the parameters */
3272   geniCodeParms (parms, NULL, &stack, ftype, lvl);
3273
3274   /* now call : if symbol then pcall */
3275   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3276     ic = newiCode (PCALL, left, NULL);
3277   } else {
3278     ic = newiCode (CALL, left, NULL);
3279   }
3280
3281   type = copyLinkChain (ftype->next);
3282   etype = getSpec (type);
3283   SPEC_EXTR (etype) = 0;
3284   IC_RESULT (ic) = result = newiTempOperand (type, 1);
3285
3286   ADDTOCHAIN (ic);
3287
3288   /* stack adjustment after call */
3289   ic->parmBytes = stack;
3290
3291   return result;
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* geniCodeReceive - generate intermediate code for "receive"      */
3296 /*-----------------------------------------------------------------*/
3297 static void 
3298 geniCodeReceive (value * args)
3299 {
3300   /* for all arguments that are passed in registers */
3301   while (args)
3302     {
3303       int first = 1;
3304       if (IS_REGPARM (args->etype))
3305         {
3306           operand *opr = operandFromValue (args);
3307           operand *opl;
3308           symbol *sym = OP_SYMBOL (opr);
3309           iCode *ic;
3310
3311           /* we will use it after all optimizations
3312              and before liveRange calculation */
3313           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3314             {
3315
3316               if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3317                   options.stackAuto == 0 &&
3318                   (!(options.model == MODEL_FLAT24)) )
3319                 {
3320                 }
3321               else
3322                 {
3323                   opl = newiTempOperand (args->type, 0);
3324                   sym->reqv = opl;
3325                   sym->reqv->key = sym->key;
3326                   OP_SYMBOL (sym->reqv)->key = sym->key;
3327                   OP_SYMBOL (sym->reqv)->isreqv = 1;
3328                   OP_SYMBOL (sym->reqv)->islocal = 0;
3329                   SPIL_LOC (sym->reqv) = sym;
3330                 }
3331             }
3332
3333           ic = newiCode (RECEIVE, NULL, NULL);    
3334           ic->argreg = SPEC_ARGREG(args->etype);
3335           if (first) {
3336               currFunc->recvSize = getSize (sym->type);
3337               first = 0;
3338           }
3339           IC_RESULT (ic) = opr;
3340           ADDTOCHAIN (ic);
3341         }
3342
3343       args = args->next;
3344     }
3345 }
3346
3347 /*-----------------------------------------------------------------*/
3348 /* geniCodeFunctionBody - create the function body                 */
3349 /*-----------------------------------------------------------------*/
3350 void 
3351 geniCodeFunctionBody (ast * tree,int lvl)
3352 {
3353   iCode *ic;
3354   operand *func;
3355   sym_link *fetype;
3356   int savelineno;
3357
3358   /* reset the auto generation */
3359   /* numbers */
3360   iTempNum = 0;
3361   iTempLblNum = 0;
3362   operandKey = 0;
3363   iCodeKey = 0;
3364   func = ast2iCode (tree->left,lvl+1);
3365   fetype = getSpec (operandType (func));
3366
3367   savelineno = lineno;
3368   lineno = OP_SYMBOL (func)->lineDef;
3369   /* create an entry label */
3370   geniCodeLabel (entryLabel);
3371   lineno = savelineno;
3372
3373   /* create a proc icode */
3374   ic = newiCode (FUNCTION, func, NULL);
3375   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3376   ic->tree = tree;
3377
3378   ADDTOCHAIN (ic);
3379
3380   /* for all parameters that are passed
3381      on registers add a "receive" */
3382   geniCodeReceive (tree->values.args);
3383
3384   /* generate code for the body */
3385   ast2iCode (tree->right,lvl+1);
3386
3387   /* create a label for return */
3388   geniCodeLabel (returnLabel);
3389
3390   /* now generate the end proc */
3391   ic = newiCode (ENDFUNCTION, func, NULL);
3392   ic->tree = tree;
3393   ADDTOCHAIN (ic);
3394   return;
3395 }
3396
3397 /*-----------------------------------------------------------------*/
3398 /* geniCodeReturn - gen icode for 'return' statement               */
3399 /*-----------------------------------------------------------------*/
3400 void 
3401 geniCodeReturn (operand * op)
3402 {
3403   iCode *ic;
3404
3405   /* if the operand is present force an rvalue */
3406   if (op)
3407     op = geniCodeRValue (op, FALSE);
3408
3409   ic = newiCode (RETURN, op, NULL);
3410   ADDTOCHAIN (ic);
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* geniCodeIfx - generates code for extended if statement          */
3415 /*-----------------------------------------------------------------*/
3416 void 
3417 geniCodeIfx (ast * tree,int lvl)
3418 {
3419   iCode *ic;
3420   operand *condition = ast2iCode (tree->left,lvl+1);
3421   sym_link *cetype;
3422
3423   /* if condition is null then exit */
3424   if (!condition)
3425     goto exit;
3426   else
3427     condition = geniCodeRValue (condition, FALSE);
3428
3429   cetype = getSpec (operandType (condition));
3430   /* if the condition is a literal */
3431   if (IS_LITERAL (cetype))
3432     {
3433       if (floatFromVal (condition->operand.valOperand))
3434         {
3435           if (tree->trueLabel)
3436             geniCodeGoto (tree->trueLabel);
3437           else
3438             assert (0);
3439         }
3440       else
3441         {
3442           if (tree->falseLabel)
3443             geniCodeGoto (tree->falseLabel);
3444           else
3445             assert (0);
3446         }
3447       goto exit;
3448     }
3449
3450   if (tree->trueLabel)
3451     {
3452       ic = newiCodeCondition (condition,
3453                               tree->trueLabel,
3454                               NULL);
3455       ADDTOCHAIN (ic);
3456
3457       if (tree->falseLabel)
3458         geniCodeGoto (tree->falseLabel);
3459     }
3460   else
3461     {
3462       ic = newiCodeCondition (condition,
3463                               NULL,
3464                               tree->falseLabel);
3465       ADDTOCHAIN (ic);
3466     }
3467
3468 exit:
3469   ast2iCode (tree->right,lvl+1);
3470 }
3471
3472 /*-----------------------------------------------------------------*/
3473 /* geniCodeJumpTable - tries to create a jump table for switch     */
3474 /*-----------------------------------------------------------------*/
3475 int 
3476 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3477 {
3478   int min, max, cnt = 1;
3479   int i, t;
3480   value *vch;
3481   iCode *ic;
3482   operand *boundary;
3483   symbol *falseLabel;
3484   set *labels = NULL;
3485   int needRangeCheck = !optimize.noJTabBoundary
3486                        || tree->values.switchVals.swDefault;
3487   sym_link *cetype = getSpec (operandType (cond));
3488   int sizeofMinCost, sizeofMaxCost;
3489   int sizeofMatchJump, sizeofJumpTable;
3490   int sizeIndex;
3491
3492   if (!tree || !caseVals)
3493     return 0;
3494
3495   /* the criteria for creating a jump table is */
3496   /* all integer numbers between the maximum & minimum must */
3497   /* be present , the maximum value should not exceed 255 */
3498   /* If not all integer numbers are present the algorithm */
3499   /* inserts jumps to the default label for the missing numbers */
3500   /* and decides later whether it is worth it */
3501   min = (int) floatFromVal (vch = caseVals);
3502
3503   while (vch->next)
3504     {
3505       cnt++;
3506       vch = vch->next;
3507     }
3508   max = (int) floatFromVal (vch);
3509
3510   /* Exit if the range is too large to handle with a jump table. */
3511   if (1 + max - min > port->jumptableCost.maxCount)
3512     return 0;
3513
3514   switch (getSize (operandType (cond)))
3515     {
3516     case 1: sizeIndex = 0; break;
3517     case 2: sizeIndex = 1; break;
3518     case 4: sizeIndex = 2; break;
3519     default: return 0;
3520     }
3521   
3522   /* Compute the size cost of the range check and subtraction. */
3523   sizeofMinCost = 0;
3524   sizeofMaxCost = 0;
3525   if (needRangeCheck)
3526     {
3527       if (!(min==0 && IS_UNSIGNED (cetype)))
3528         sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3529       sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3530     }
3531   if (min)
3532     sizeofMinCost += port->jumptableCost.sizeofSubtract;
3533   
3534   /* If the size cost of handling a non-zero minimum exceeds the */
3535   /* cost of extending the range down to zero, then it might be */
3536   /* better to extend the range to zero. */
3537   if (min > 0 && sizeofMinCost >= (min * port->jumptableCost.sizeofElement))
3538     {
3539       /* Only extend the jump table if it would still be manageable. */
3540       if (1 + max <= port->jumptableCost.maxCount)
3541         min = 0;
3542     }
3543     
3544   /* Compute the total size cost of a jump table. */
3545   sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3546                      + port->jumptableCost.sizeofDispatch
3547                      + sizeofMinCost + sizeofMaxCost;
3548
3549   /* Compute the total size cost of a match & jump sequence */
3550   sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3551   
3552   /* If the size cost of the jump table is uneconomical then exit */
3553   if (sizeofMatchJump <  sizeofJumpTable)
3554     return 0;
3555
3556   /* The jump table is preferable. */
3557   
3558   /* First, a label for the default or missing cases. */
3559   if (tree->values.switchVals.swDefault)
3560     {
3561       SNPRINTF (buffer, sizeof(buffer),
3562                 "_default_%d",
3563                 tree->values.switchVals.swNum);
3564     }
3565   else
3566     {
3567       SNPRINTF (buffer, sizeof(buffer),
3568                 "_swBrk_%d",
3569                 tree->values.switchVals.swNum);
3570     }
3571   falseLabel = newiTempLabel (buffer);
3572
3573   /* Build the list of labels for the jump table. */
3574   vch = caseVals;
3575   t = (int) floatFromVal (vch);
3576   for (i=min; i<=max; i++)
3577     {
3578       if (vch && t==i)
3579         {
3580           /* Explicit case: make a new label for it. */
3581           SNPRINTF (buffer, sizeof(buffer), 
3582                     "_case_%d_%d",
3583                     tree->values.switchVals.swNum,
3584                     i);
3585           addSet (&labels, newiTempLabel (buffer));
3586           vch = vch->next;
3587           if (vch)
3588             t = (int) floatFromVal (vch);
3589         }
3590       else
3591         {
3592           /* Implicit case: use the default label. */
3593           addSet (&labels, falseLabel);
3594         }
3595     }
3596
3597   /* If cond is volatile, it might change after the boundary  */
3598   /* conditions are tested to an out of bounds value, causing */
3599   /* a jump to a location outside of the jump table. To avoid */
3600   /* this possibility, use a non-volatile copy of it instead. */
3601   if (IS_OP_VOLATILE (cond))
3602     {
3603       operand * newcond;
3604       iCode * ic;
3605       
3606       newcond = newiTempOperand (operandType (cond), TRUE);
3607       newcond->isvolatile = 0;
3608       ic = newiCode ('=', NULL, cond);
3609       IC_RESULT (ic) = newcond;
3610       ADDTOCHAIN (ic);
3611       cond = newcond;
3612     }
3613
3614   /* first we rule out the boundary conditions */
3615   /* if only optimization says so */
3616   if (needRangeCheck)
3617     {
3618       sym_link *cetype = getSpec (operandType (cond));
3619       /* no need to check the lower bound if
3620          the condition is unsigned & minimum value is zero */
3621       if (!(min == 0 && IS_UNSIGNED (cetype)))
3622         {
3623           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3624           ic = newiCodeCondition (boundary, falseLabel, NULL);
3625           ADDTOCHAIN (ic);
3626         }
3627
3628       /* now for upper bounds */
3629       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3630       ic = newiCodeCondition (boundary, falseLabel, NULL);
3631       ADDTOCHAIN (ic);
3632     }
3633
3634   /* if the min is not zero then we no make it zero */
3635   if (min)
3636     {
3637       cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3638       if (!IS_LITERAL(getSpec(operandType(cond))))
3639         setOperandType (cond, UCHARTYPE);
3640     }
3641
3642   /* now create the jumptable */
3643   ic = newiCode (JUMPTABLE, NULL, NULL);
3644   IC_JTCOND (ic) = cond;
3645   IC_JTLABELS (ic) = labels;
3646   ADDTOCHAIN (ic);
3647   return 1;
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* geniCodeSwitch - changes a switch to a if statement             */
3652 /*-----------------------------------------------------------------*/
3653 void
3654 geniCodeSwitch (ast * tree,int lvl)
3655 {
3656   iCode *ic;
3657   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3658   value *caseVals = tree->values.switchVals.swVals;
3659   symbol *trueLabel, *falseLabel;
3660       
3661   /* If the condition is a literal, then just jump to the */
3662   /* appropriate case label. */
3663   if (IS_LITERAL(getSpec(operandType(cond))))
3664     {
3665       int switchVal, caseVal;
3666       
3667       switchVal = (int) floatFromVal (cond->operand.valOperand);
3668       while (caseVals)
3669         {
3670           caseVal = (int) floatFromVal (caseVals);
3671           if (caseVal == switchVal)
3672             {
3673               SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3674                         tree->values.switchVals.swNum, caseVal);
3675               trueLabel = newiTempLabel (buffer);
3676               geniCodeGoto (trueLabel);
3677               goto jumpTable;
3678             }
3679           caseVals = caseVals->next;
3680         }
3681       goto defaultOrBreak;
3682     }
3683
3684   /* if we can make this a jump table */
3685   if (geniCodeJumpTable (cond, caseVals, tree))
3686     goto jumpTable;             /* no need for the comparison */
3687
3688   /* for the cases defined do */
3689   while (caseVals)
3690     {
3691
3692       operand *compare = geniCodeLogic (cond,
3693                                         operandFromValue (caseVals),
3694                                         EQ_OP);
3695
3696       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3697                tree->values.switchVals.swNum,
3698                (int) floatFromVal (caseVals));
3699       trueLabel = newiTempLabel (buffer);
3700
3701       ic = newiCodeCondition (compare, trueLabel, NULL);
3702       ADDTOCHAIN (ic);
3703       caseVals = caseVals->next;
3704     }
3705
3706
3707 defaultOrBreak:
3708   /* if default is present then goto break else break */
3709   if (tree->values.switchVals.swDefault)
3710     {
3711         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3712     }
3713   else
3714     {
3715         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3716     }
3717
3718   falseLabel = newiTempLabel (buffer);
3719   geniCodeGoto (falseLabel);
3720
3721 jumpTable:
3722   ast2iCode (tree->right,lvl+1);
3723 }
3724
3725 /*-----------------------------------------------------------------*/
3726 /* geniCodeInline - intermediate code for inline assembler         */
3727 /*-----------------------------------------------------------------*/
3728 static void 
3729 geniCodeInline (ast * tree)
3730 {
3731   iCode *ic;
3732
3733   ic = newiCode (INLINEASM, NULL, NULL);
3734   IC_INLINE (ic) = tree->values.inlineasm;
3735   ADDTOCHAIN (ic);
3736 }
3737
3738 /*-----------------------------------------------------------------*/
3739 /* geniCodeArrayInit - intermediate code for array initializer     */
3740 /*-----------------------------------------------------------------*/
3741 static void
3742 geniCodeArrayInit (ast * tree, operand *array)
3743 {
3744   iCode *ic;
3745
3746   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3747     ic = newiCode (ARRAYINIT, array, NULL);
3748     IC_ARRAYILIST (ic) = tree->values.constlist;
3749   } else {
3750     operand *left=newOperand(), *right=newOperand();
3751     left->type=right->type=SYMBOL;
3752     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3753     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3754     ic = newiCode (ARRAYINIT, left, right);
3755   }
3756   ADDTOCHAIN (ic);
3757 }
3758         
3759 /*-----------------------------------------------------------------*/
3760 /* geniCodeCritical - intermediate code for a critical statement   */
3761 /*-----------------------------------------------------------------*/
3762 static void 
3763 geniCodeCritical (ast *tree, int lvl)
3764 {
3765   iCode *ic;
3766   operand *op = NULL;
3767
3768   /* If op is NULL, the original interrupt state will saved on */
3769   /* the stack. Otherwise, it will be saved in op. */
3770   
3771   /* Generate a save of the current interrupt state & disabled */
3772   ic = newiCode (CRITICAL, NULL, NULL);
3773   IC_RESULT (ic) = op;
3774   ADDTOCHAIN (ic);
3775   
3776   /* Generate the critical code sequence */
3777   if (tree->left && tree->left->type == EX_VALUE)
3778     geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3779   else
3780     ast2iCode (tree->left,lvl+1);
3781   
3782   /* Generate a restore of the original interrupt state */
3783   ic = newiCode (ENDCRITICAL, NULL, op);
3784   ADDTOCHAIN (ic);
3785 }
3786
3787 /*-----------------------------------------------------------------*/
3788 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3789 /* particular case. Ie : assigning or dereferencing array or ptr   */
3790 /*-----------------------------------------------------------------*/
3791 set * lvaluereqSet = NULL;
3792 typedef struct lvalItem
3793   {
3794     int req;
3795     int lvl;
3796   }
3797 lvalItem;
3798
3799 /*-----------------------------------------------------------------*/
3800 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3801 /*-----------------------------------------------------------------*/
3802 void addLvaluereq(int lvl)
3803 {
3804   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3805   lpItem->req=1;
3806   lpItem->lvl=lvl;
3807   addSetHead(&lvaluereqSet,lpItem);
3808
3809 }
3810 /*-----------------------------------------------------------------*/
3811 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3812 /*-----------------------------------------------------------------*/
3813 void delLvaluereq()
3814 {
3815   lvalItem * lpItem;
3816   lpItem = getSet(&lvaluereqSet);
3817   if(lpItem) Safe_free(lpItem);
3818 }
3819 /*-----------------------------------------------------------------*/
3820 /* clearLvaluereq - clear lvalreq flag                             */
3821 /*-----------------------------------------------------------------*/
3822 void clearLvaluereq()
3823 {
3824   lvalItem * lpItem;
3825   lpItem = peekSet(lvaluereqSet);
3826   if(lpItem) lpItem->req = 0;
3827 }
3828 /*-----------------------------------------------------------------*/
3829 /* getLvaluereq - get the last lvalreq level                       */
3830 /*-----------------------------------------------------------------*/
3831 int getLvaluereqLvl()
3832 {
3833   lvalItem * lpItem;
3834   lpItem = peekSet(lvaluereqSet);
3835   if(lpItem) return lpItem->lvl;
3836   return 0;
3837 }
3838 /*-----------------------------------------------------------------*/
3839 /* isLvaluereq - is lvalreq valid for this level ?                 */
3840 /*-----------------------------------------------------------------*/
3841 int isLvaluereq(int lvl)
3842 {
3843   lvalItem * lpItem;
3844   lpItem = peekSet(lvaluereqSet);
3845   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3846   return 0;
3847 }
3848
3849 /*-----------------------------------------------------------------*/
3850 /* ast2iCode - creates an icodeList from an ast                    */
3851 /*-----------------------------------------------------------------*/
3852 operand *
3853 ast2iCode (ast * tree,int lvl)
3854 {
3855   operand *left = NULL;
3856   operand *right = NULL;
3857   if (!tree)
3858     return NULL;
3859
3860   /* set the global variables for filename & line number */
3861   if (tree->filename)
3862     filename = tree->filename;
3863   if (tree->lineno)
3864     lineno = tree->lineno;
3865   if (tree->block)
3866     block = tree->block;
3867   if (tree->level)
3868     scopeLevel = tree->level;
3869   if (tree->seqPoint)
3870     seqPoint = tree->seqPoint;
3871
3872   if (tree->type == EX_VALUE)
3873     return operandFromValue (tree->opval.val);
3874
3875   if (tree->type == EX_LINK)
3876     return operandFromLink (tree->opval.lnk);
3877
3878   /* if we find a nullop */
3879   if (tree->type == EX_OP &&
3880      (tree->opval.op == NULLOP ||
3881      tree->opval.op == BLOCK))
3882     {
3883       if (tree->left && tree->left->type == EX_VALUE)
3884         geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3885       else
3886         ast2iCode (tree->left,lvl+1);
3887       if (tree->right && tree->right->type == EX_VALUE)
3888         geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3889       else
3890         ast2iCode (tree->right,lvl+1);
3891       return NULL;
3892     }
3893
3894   /* special cases for not evaluating */
3895   if (tree->opval.op != ':' &&
3896       tree->opval.op != '?' &&
3897       tree->opval.op != CALL &&
3898       tree->opval.op != IFX &&
3899       tree->opval.op != AND_OP &&
3900       tree->opval.op != OR_OP &&
3901       tree->opval.op != LABEL &&
3902       tree->opval.op != GOTO &&
3903       tree->opval.op != SWITCH &&
3904       tree->opval.op != FUNCTION &&
3905       tree->opval.op != INLINEASM &&
3906       tree->opval.op != CRITICAL)
3907     {
3908
3909         if (IS_ASSIGN_OP (tree->opval.op) ||
3910            IS_DEREF_OP (tree) ||
3911            (tree->opval.op == '&' && !tree->right) ||
3912            tree->opval.op == PTR_OP)
3913           {
3914             addLvaluereq(lvl);
3915             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3916                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3917               clearLvaluereq();
3918
3919             left = operandFromAst (tree->left,lvl);
3920             delLvaluereq();
3921             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3922               left = geniCodeRValue (left, TRUE);
3923           }
3924         else
3925           {
3926             left = operandFromAst (tree->left,lvl);
3927           }
3928         if (tree->opval.op == INC_OP ||
3929             tree->opval.op == DEC_OP)
3930           {
3931             addLvaluereq(lvl);
3932             right = operandFromAst (tree->right,lvl);
3933             delLvaluereq();
3934           }
3935         else
3936           {
3937             right = operandFromAst (tree->right,lvl);
3938           }
3939       }
3940
3941   /* now depending on the type of operand */
3942   /* this will be a biggy                 */
3943   switch (tree->opval.op)
3944     {
3945
3946     case '[':                   /* array operation */
3947       {
3948         //sym_link *ltype = operandType (left);
3949         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3950         left = geniCodeRValue (left, FALSE);
3951         right = geniCodeRValue (right, TRUE);
3952       }
3953
3954       return geniCodeArray (left, right,lvl);
3955
3956     case '.':                   /* structure dereference */
3957       if (IS_PTR (operandType (left)))
3958         left = geniCodeRValue (left, TRUE);
3959       else
3960         left = geniCodeRValue (left, FALSE);
3961
3962       return geniCodeStruct (left, right, tree->lvalue);
3963
3964     case PTR_OP:                /* structure pointer dereference */
3965       {
3966         sym_link *pType;
3967         pType = operandType (left);
3968         left = geniCodeRValue (left, TRUE);
3969
3970         setOClass (pType, getSpec (operandType (left)));
3971       }
3972
3973       return geniCodeStruct (left, right, tree->lvalue);
3974
3975     case INC_OP:                /* increment operator */
3976       if (left)
3977         return geniCodePostInc (left);
3978       else
3979         return geniCodePreInc (right, tree->lvalue);
3980
3981     case DEC_OP:                /* decrement operator */
3982       if (left)
3983         return geniCodePostDec (left);
3984       else
3985         return geniCodePreDec (right, tree->lvalue);
3986
3987     case '&':                   /* bitwise and or address of operator */
3988       if (right)
3989         {                       /* this is a bitwise operator   */
3990           left = geniCodeRValue (left, FALSE);
3991           right = geniCodeRValue (right, FALSE);
3992           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3993         }
3994       else
3995         return geniCodeAddressOf (left);
3996
3997     case '|':                   /* bitwise or & xor */
3998     case '^':
3999       return geniCodeBitwise (geniCodeRValue (left, FALSE),
4000                               geniCodeRValue (right, FALSE),
4001                               tree->opval.op,
4002                               tree->ftype);
4003
4004     case '/':
4005       return geniCodeDivision (geniCodeRValue (left, FALSE),
4006                                geniCodeRValue (right, FALSE),
4007                                getResultTypeFromType (tree->ftype));
4008
4009     case '%':
4010       return geniCodeModulus (geniCodeRValue (left, FALSE),
4011                               geniCodeRValue (right, FALSE),
4012                               getResultTypeFromType (tree->ftype));
4013     case '*':
4014       if (right)
4015         return geniCodeMultiply (geniCodeRValue (left, FALSE),
4016                                  geniCodeRValue (right, FALSE),
4017                                  getResultTypeFromType (tree->ftype));
4018       else
4019         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4020
4021     case '-':
4022       if (right)
4023         return geniCodeSubtract (geniCodeRValue (left, FALSE),
4024                                  geniCodeRValue (right, FALSE),
4025                                  getResultTypeFromType (tree->ftype));
4026       else
4027         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4028
4029     case '+':
4030       if (right)
4031         return geniCodeAdd (geniCodeRValue (left, FALSE),
4032                             geniCodeRValue (right, FALSE),
4033                             getResultTypeFromType (tree->ftype),
4034                             lvl);
4035       else
4036         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
4037
4038     case LEFT_OP:
4039       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4040                                 geniCodeRValue (right, FALSE),
4041                                 getResultTypeFromType (tree->ftype));
4042
4043     case RIGHT_OP:
4044       return geniCodeRightShift (geniCodeRValue (left, FALSE),
4045                                  geniCodeRValue (right, FALSE));
4046     case CAST:
4047 #if 0 // this indeed needs a second thought
4048       {
4049         operand *op;
4050
4051         // let's keep this simple: get the rvalue we need
4052         op=geniCodeRValue (right, FALSE);
4053         // now cast it to whatever we want
4054         op=geniCodeCast (operandType(left), op, FALSE);
4055         // if this is going to be used as an lvalue, make it so
4056         if (tree->lvalue) {
4057           op->isaddr=1;
4058         }
4059         return op;
4060       }
4061 #else // bug #604575, is it a bug ????
4062       return geniCodeCast (operandType (left),
4063                            geniCodeRValue (right, FALSE), FALSE);
4064 #endif
4065
4066     case '~':
4067     case RRC:
4068     case RLC:
4069     case SWAP:
4070       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4071
4072     case '!':
4073     case GETHBIT:
4074       {
4075         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4076         setOperandType (op, UCHARTYPE);
4077         return op;
4078       }
4079     case AND_OP:
4080     case OR_OP:
4081       return geniCodeLogicAndOr (tree, lvl);
4082     case '>':
4083     case '<':
4084     case LE_OP:
4085     case GE_OP:
4086     case EQ_OP:
4087     case NE_OP:
4088       /* different compilers (even different gccs) evaluate
4089          the two calls in a different order. to get the same
4090          result on all machines we've to specify a clear sequence.
4091       return geniCodeLogic (geniCodeRValue (left, FALSE),
4092                             geniCodeRValue (right, FALSE),
4093                             tree->opval.op);
4094       */
4095       {
4096         operand *leftOp, *rightOp;
4097
4098         leftOp  = geniCodeRValue (left , FALSE);
4099         rightOp = geniCodeRValue (right, FALSE);
4100
4101         return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4102       }
4103     case '?':
4104       return geniCodeConditional (tree,lvl);
4105
4106     case SIZEOF:
4107       return operandFromLit (getSize (tree->right->ftype));
4108
4109     case '=':
4110       {
4111         sym_link *rtype = operandType (right);
4112         sym_link *ltype = operandType (left);
4113         if (IS_PTR (rtype) && IS_ITEMP (right)
4114             && right->isaddr && compareType (rtype->next, ltype) == 1)
4115           right = geniCodeRValue (right, TRUE);
4116         else
4117           right = geniCodeRValue (right, FALSE);
4118
4119         geniCodeAssign (left, right, 0, 1);
4120         return right;
4121       }
4122     case MUL_ASSIGN:
4123       return
4124         geniCodeAssign (left,
4125                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4126                                                   FALSE),
4127                                   geniCodeRValue (right, FALSE), 
4128                                   getResultTypeFromType (tree->ftype)),
4129                         0, 1);
4130
4131     case DIV_ASSIGN:
4132       return
4133         geniCodeAssign (left,
4134                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4135                                                   FALSE),
4136                                   geniCodeRValue (right, FALSE),
4137                                   getResultTypeFromType (tree->ftype)),
4138                         0, 1);
4139     case MOD_ASSIGN:
4140       return
4141         geniCodeAssign (left,
4142                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4143                                                   FALSE),
4144                                   geniCodeRValue (right, FALSE),
4145                                   getResultTypeFromType (tree->ftype)),
4146                         0, 1);
4147     case ADD_ASSIGN:
4148       {
4149         sym_link *rtype = operandType (right);
4150         sym_link *ltype = operandType (left);
4151         if (IS_PTR (rtype) && IS_ITEMP (right)
4152             && right->isaddr && compareType (rtype->next, ltype) == 1)
4153           right = geniCodeRValue (right, TRUE);
4154         else
4155           right = geniCodeRValue (right, FALSE);
4156
4157
4158         return geniCodeAssign (left,
4159                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4160                                                   FALSE),
4161                                   right,
4162                                   getResultTypeFromType (tree->ftype),
4163                                   lvl),
4164                                0, 1);
4165       }
4166     case SUB_ASSIGN:
4167       {
4168         sym_link *rtype = operandType (right);
4169         sym_link *ltype = operandType (left);
4170         if (IS_PTR (rtype) && IS_ITEMP (right)
4171             && right->isaddr && compareType (rtype->next, ltype) == 1)
4172           {
4173             right = geniCodeRValue (right, TRUE);
4174           }
4175         else
4176           {
4177             right = geniCodeRValue (right, FALSE);
4178           }
4179         return
4180           geniCodeAssign (left,
4181                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4182                                                   FALSE),
4183                                   right,
4184                                   getResultTypeFromType (tree->ftype)),
4185                           0, 1);
4186       }
4187     case LEFT_ASSIGN:
4188       return
4189         geniCodeAssign (left,
4190                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4191                                                    ,FALSE),
4192                                    geniCodeRValue (right, FALSE),
4193                                    getResultTypeFromType (tree->ftype)),
4194                         0, 1);
4195     case RIGHT_ASSIGN:
4196       return
4197         geniCodeAssign (left,
4198                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4199                                                    ,FALSE),
4200                                    geniCodeRValue (right, FALSE)), 0, 1);
4201     case AND_ASSIGN:
4202       return
4203         geniCodeAssign (left,
4204                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4205                                                   FALSE),
4206                                   geniCodeRValue (right, FALSE),
4207                                   BITWISEAND,
4208                                   operandType (left)), 0, 1);
4209     case XOR_ASSIGN:
4210       return
4211         geniCodeAssign (left,
4212                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4213                                                   FALSE),
4214                                   geniCodeRValue (right, FALSE),
4215                                   '^',
4216                                   operandType (left)), 0, 1);
4217     case OR_ASSIGN:
4218       return
4219         geniCodeAssign (left,
4220                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4221                                                    ,FALSE),
4222                                    geniCodeRValue (right, FALSE),
4223                                    '|',
4224                                    operandType (left)), 0, 1);
4225     case ',':
4226       return geniCodeRValue (right, FALSE);
4227
4228     case CALL:
4229       return geniCodeCall (ast2iCode (tree->left,lvl+1),
4230                            tree->right,lvl);
4231     case LABEL:
4232       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4233       return ast2iCode (tree->right,lvl+1);
4234
4235     case GOTO:
4236       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4237       return ast2iCode (tree->right,lvl+1);
4238
4239     case FUNCTION:
4240       geniCodeFunctionBody (tree,lvl);
4241       return NULL;
4242
4243     case RETURN:
4244       geniCodeReturn (right);
4245       return NULL;
4246
4247     case IFX:
4248       geniCodeIfx (tree,lvl);
4249       return NULL;
4250
4251     case SWITCH:
4252       geniCodeSwitch (tree,lvl);
4253       return NULL;
4254
4255     case INLINEASM:
4256       geniCodeInline (tree);
4257       return NULL;
4258         
4259     case ARRAYINIT:
4260         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4261         return NULL;
4262     
4263     case CRITICAL:
4264         geniCodeCritical (tree, lvl);
4265     }
4266
4267   return NULL;
4268 }
4269
4270 /*-----------------------------------------------------------------*/
4271 /* reverseICChain - gets from the list and creates a linkedlist    */
4272 /*-----------------------------------------------------------------*/
4273 iCode *
4274 reverseiCChain ()
4275 {
4276   iCode *loop = NULL;
4277   iCode *prev = NULL;
4278
4279   while ((loop = getSet (&iCodeChain)))
4280     {
4281       loop->next = prev;
4282       if (prev)
4283         prev->prev = loop;
4284       prev = loop;
4285     }
4286
4287   return prev;
4288 }
4289
4290
4291 /*-----------------------------------------------------------------*/
4292 /* iCodeFromAst - given an ast will convert it to iCode            */
4293 /*-----------------------------------------------------------------*/
4294 iCode *
4295 iCodeFromAst (ast * tree)
4296 {
4297   returnLabel = newiTempLabel ("_return");
4298   entryLabel = newiTempLabel ("_entry");
4299   ast2iCode (tree,0);
4300   return reverseiCChain ();
4301 }
4302
4303 static const char *opTypeToStr(OPTYPE op)
4304 {
4305     switch(op)
4306     {
4307       case SYMBOL: return "symbol";
4308       case VALUE: return "value";
4309       case TYPE: return "type";
4310     }
4311     return "undefined type";    
4312 }
4313
4314
4315 operand *validateOpType(operand         *op, 
4316                         const char      *macro,
4317                         const char      *args,
4318                         OPTYPE          type,
4319                         const char      *file, 
4320                         unsigned        line)
4321 {    
4322     if (op && op->type == type)
4323     {
4324         return op;
4325     }
4326     fprintf(stderr, 
4327             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4328             " expected %s, got %s\n",
4329             macro, args, file, line, 
4330             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4331     exit(-1);
4332     return op; // never reached, makes compiler happy.
4333 }