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