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